@natachah/vanilla-frontend 0.1.17 → 0.1.19
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/pages/base/typography.html +5 -4
- package/docs/pages/components/button.html +7 -4
- package/docs/pages/components/dialog.html +1 -1
- package/docs/pages/components/disclosure.html +9 -6
- package/docs/pages/components/dropdown.html +7 -4
- package/docs/pages/components/form.html +50 -11
- package/docs/pages/components/list.html +7 -4
- package/docs/pages/javascript/tree.html +19 -1
- package/docs/pages/quick-start/customization.html +31 -17
- package/docs/src/js/doc-layout.js +1 -1
- package/docs/src/scss/layout.scss +4 -0
- package/js/_dialog.js +15 -2
- package/js/_drawer.js +1 -1
- package/js/_dropdown.js +1 -1
- package/js/_sortable.js +2 -4
- package/js/_toggle.js +4 -1
- package/js/_tree.js +87 -10
- package/js/tests/drawer.test.js +1 -1
- package/natachah-vanilla-frontend-0.1.19.tgz +0 -0
- package/package.json +1 -1
- package/scss/abstracts/_mixins.scss +18 -10
- package/scss/base/_typography.scss +4 -2
- package/scss/themes/_root.scss +5 -5
- package/natachah-vanilla-frontend-0.1.17.tgz +0 -0
|
@@ -94,12 +94,13 @@
|
|
|
94
94
|
--anchor-decoration
|
|
95
95
|
--anchor-color
|
|
96
96
|
--anchor-hover-color
|
|
97
|
+
--anchor-focus-color
|
|
97
98
|
--anchor-active-color
|
|
98
99
|
--anchor-disabled-opacity
|
|
99
|
-
--anchor-
|
|
100
|
-
--anchor-
|
|
101
|
-
--anchor-
|
|
102
|
-
--anchor-
|
|
100
|
+
--anchor-outline-size
|
|
101
|
+
--anchor-outline-style
|
|
102
|
+
--anchor-outline-color
|
|
103
|
+
--anchor-outline-offset
|
|
103
104
|
</doc-code>
|
|
104
105
|
</div>
|
|
105
106
|
|
|
@@ -42,13 +42,16 @@
|
|
|
42
42
|
--button-padding-block
|
|
43
43
|
--button-transition
|
|
44
44
|
--button-decoration
|
|
45
|
-
--button-
|
|
46
|
-
--button-
|
|
47
|
-
--button-
|
|
48
|
-
--button-
|
|
45
|
+
--button-outline-size
|
|
46
|
+
--button-outline-style
|
|
47
|
+
--button-outline-color
|
|
48
|
+
--button-outline-offset
|
|
49
49
|
--button-hover-color
|
|
50
50
|
--button-hover-background
|
|
51
51
|
--button-hover-border-color
|
|
52
|
+
--button-focus-color
|
|
53
|
+
--button-focus-background
|
|
54
|
+
--button-focus-border-color
|
|
52
55
|
--button-active-color
|
|
53
56
|
--button-active-background
|
|
54
57
|
--button-active-border-color
|
|
@@ -65,13 +65,16 @@
|
|
|
65
65
|
--disclosure-padding-block
|
|
66
66
|
--disclosure-transition
|
|
67
67
|
--disclosure-decoration
|
|
68
|
-
--disclosure-
|
|
69
|
-
--disclosure-
|
|
70
|
-
--disclosure-
|
|
71
|
-
--disclosure-
|
|
68
|
+
--disclosure-outline-size
|
|
69
|
+
--disclosure-outline-style
|
|
70
|
+
--disclosure-outline-color
|
|
71
|
+
--disclosure-outline-offset
|
|
72
72
|
--disclosure-hover-color
|
|
73
73
|
--disclosure-hover-background
|
|
74
74
|
--disclosure-hover-border-color
|
|
75
|
+
--disclosure-focus-color
|
|
76
|
+
--disclosure-focus-background
|
|
77
|
+
--disclosure-focus-border-color
|
|
75
78
|
--disclosure-active-color
|
|
76
79
|
--disclosure-active-background
|
|
77
80
|
--disclosure-active-border-color
|
|
@@ -130,7 +133,7 @@
|
|
|
130
133
|
</doc-code>
|
|
131
134
|
<doc-code id="scss" data-type="scss" role="tabpanel">
|
|
132
135
|
$outline-variations: (
|
|
133
|
-
|
|
136
|
+
disclosure
|
|
134
137
|
);
|
|
135
138
|
</doc-code>
|
|
136
139
|
</div>
|
|
@@ -224,7 +227,7 @@
|
|
|
224
227
|
</doc-code>
|
|
225
228
|
<doc-code id="scss" data-type="scss" role="tabpanel">
|
|
226
229
|
$color-variations: (
|
|
227
|
-
|
|
230
|
+
disclosure: (primary)
|
|
228
231
|
);
|
|
229
232
|
</doc-code>
|
|
230
233
|
</div>
|
|
@@ -69,13 +69,16 @@
|
|
|
69
69
|
--dropdown-padding-block
|
|
70
70
|
--dropdown-transition
|
|
71
71
|
--dropdown-decoration
|
|
72
|
-
--dropdown-
|
|
73
|
-
--dropdown-
|
|
74
|
-
--dropdown-
|
|
75
|
-
--dropdown-
|
|
72
|
+
--dropdown-outline-size
|
|
73
|
+
--dropdown-outline-style
|
|
74
|
+
--dropdown-outline-color
|
|
75
|
+
--dropdown-outline-offset
|
|
76
76
|
--dropdown-hover-color
|
|
77
77
|
--dropdown-hover-background
|
|
78
78
|
--dropdown-hover-border-color
|
|
79
|
+
--dropdown-focus-color
|
|
80
|
+
--dropdown-focus-background
|
|
81
|
+
--dropdown-focus-border-color
|
|
79
82
|
--dropdown-active-color
|
|
80
83
|
--dropdown-active-background
|
|
81
84
|
--dropdown-active-border-color
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
--form-padding-block
|
|
48
48
|
--form-transition
|
|
49
49
|
--form-decoration
|
|
50
|
-
--form-
|
|
51
|
-
--form-
|
|
52
|
-
--form-
|
|
53
|
-
--form-
|
|
50
|
+
--form-outline-size
|
|
51
|
+
--form-outline-style
|
|
52
|
+
--form-outline-color
|
|
53
|
+
--form-outline-offset
|
|
54
54
|
--form-disabled-opacity
|
|
55
55
|
</doc-code>
|
|
56
56
|
</div>
|
|
@@ -291,16 +291,55 @@
|
|
|
291
291
|
<p>As every design is different, there is no default style for in/valid elements</p>
|
|
292
292
|
</blockquote>
|
|
293
293
|
|
|
294
|
-
<doc-
|
|
295
|
-
<
|
|
296
|
-
|
|
297
|
-
<
|
|
298
|
-
|
|
299
|
-
|
|
294
|
+
<doc-demo>
|
|
295
|
+
<div>
|
|
296
|
+
<label for="invalidInput">Invalid input</label>
|
|
297
|
+
<input id="invalidInput" type="text" aria-describedby="invalidMsg" aria-invalid="true" value="My bad value">
|
|
298
|
+
<small id="invalidMsg">
|
|
299
|
+
<span aria-live="assertive">Incorrect value !</span>
|
|
300
|
+
</small>
|
|
301
|
+
</div>
|
|
302
|
+
<label for="validInput">Valid input</label>
|
|
303
|
+
<input id="validInput" type="text" aria-describedby="validMsg" aria-invalid="false" value="My good value">
|
|
300
304
|
<small id="validMsg">
|
|
301
305
|
<span aria-live="assertive">All good !</span>
|
|
302
306
|
</small>
|
|
303
|
-
</doc-
|
|
307
|
+
</doc-demo>
|
|
308
|
+
|
|
309
|
+
<div class="code-group">
|
|
310
|
+
<div role="tablist">
|
|
311
|
+
<button role="tab" aria-controls="html">HTML</button>
|
|
312
|
+
<button role="tab" aria-controls="scss">SCSS</button>
|
|
313
|
+
</div>
|
|
314
|
+
<doc-code id="html" data-type="html" role="tabpanel">
|
|
315
|
+
<label for="invalidInput">Invalid input</label>
|
|
316
|
+
<input id="invalidInput" type="text" aria-describedby="invalidMsg" aria-invalid="true" value="My bad value">
|
|
317
|
+
<small id="invalidMsg">
|
|
318
|
+
<span aria-live="assertive">Incorrect value !</span>
|
|
319
|
+
</small>
|
|
320
|
+
<label for="validInput">Valid input</label>
|
|
321
|
+
<input id="validInput" type="text" aria-describedby="validMsg" aria-invalid="false" value="My good value">
|
|
322
|
+
<small id="validMsg">
|
|
323
|
+
<span aria-live="assertive">All good !</span>
|
|
324
|
+
</small>
|
|
325
|
+
</doc-code>
|
|
326
|
+
<doc-code id="scss" data-type="css" role="tabpanel">
|
|
327
|
+
form {
|
|
328
|
+
div:has([aria-invalid=true]) {
|
|
329
|
+
|
|
330
|
+
--form-border-color: var(--color-error);
|
|
331
|
+
|
|
332
|
+
> label,
|
|
333
|
+
> small {
|
|
334
|
+
color: var(--color-error);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
</doc-code>
|
|
340
|
+
</div>
|
|
341
|
+
|
|
342
|
+
|
|
304
343
|
|
|
305
344
|
<h2>Variants</h2>
|
|
306
345
|
<h3>Group</h3>
|
|
@@ -88,13 +88,16 @@
|
|
|
88
88
|
<doc-code id="css" data-type="css" role="tabpanel">
|
|
89
89
|
--list-transition
|
|
90
90
|
--list-decoration
|
|
91
|
-
--list-
|
|
92
|
-
--list-
|
|
93
|
-
--list-
|
|
94
|
-
--list-
|
|
91
|
+
--list-outline-size
|
|
92
|
+
--list-outline-style
|
|
93
|
+
--list-outline-color
|
|
94
|
+
--list-outline-offset
|
|
95
95
|
--list-hover-color
|
|
96
96
|
--list-hover-background
|
|
97
97
|
--list-hover-border-color
|
|
98
|
+
--list-focus-color
|
|
99
|
+
--list-focus-background
|
|
100
|
+
--list-focus-border-color
|
|
98
101
|
--list-active-color
|
|
99
102
|
--list-active-background
|
|
100
103
|
--list-active-border-color
|
|
@@ -198,7 +198,25 @@
|
|
|
198
198
|
|
|
199
199
|
<h2>Javascript</h2>
|
|
200
200
|
<p>To enable this component you need to import the javascript file and create a new Tree object.</p>
|
|
201
|
-
|
|
201
|
+
<h3>Methods</h3>
|
|
202
|
+
<table>
|
|
203
|
+
<thead>
|
|
204
|
+
<tr>
|
|
205
|
+
<th>Method</th>
|
|
206
|
+
<th>Description</th>
|
|
207
|
+
</tr>
|
|
208
|
+
</thead>
|
|
209
|
+
<tbody>
|
|
210
|
+
<tr>
|
|
211
|
+
<td data-label="Method">
|
|
212
|
+
<p>resetEvents()</p>
|
|
213
|
+
</td>
|
|
214
|
+
<td data-label="Description">
|
|
215
|
+
<p>This method will reset the items and events</p>
|
|
216
|
+
</td>
|
|
217
|
+
</tr>
|
|
218
|
+
</tbody>
|
|
219
|
+
</table>
|
|
202
220
|
<h3>Events</h3>
|
|
203
221
|
<table>
|
|
204
222
|
<thead>
|
|
@@ -55,11 +55,11 @@
|
|
|
55
55
|
--border-style: solid;
|
|
56
56
|
--border-radius: .25rem;
|
|
57
57
|
|
|
58
|
-
//
|
|
59
|
-
--
|
|
60
|
-
--
|
|
61
|
-
--
|
|
62
|
-
--
|
|
58
|
+
// Outline (:focus)
|
|
59
|
+
--outline-size: 3px;
|
|
60
|
+
--outline-style: solid;
|
|
61
|
+
--outline-offset: 0;
|
|
62
|
+
--outline-opacity: 50%;
|
|
63
63
|
|
|
64
64
|
// Hover (color-mix)
|
|
65
65
|
--hover-color: black;
|
|
@@ -84,12 +84,26 @@
|
|
|
84
84
|
--color-warning-contrast: black;
|
|
85
85
|
|
|
86
86
|
// Icons
|
|
87
|
-
--icon-date: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="black" viewBox="0 0 16 16"
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
--icon-
|
|
91
|
-
|
|
92
|
-
|
|
87
|
+
--icon-date: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="black" viewBox="0 0 16 16">
|
|
88
|
+
<path d="M3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5zM1 4v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4H1z" />
|
|
89
|
+
</svg>');
|
|
90
|
+
--icon-time: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
|
|
91
|
+
<path d="M8 3.5a.5.5 0 0 0-1 0V9a.5.5 0 0 0 .252.434l3.5 2a.5.5 0 0 0 .496-.868L8 8.71V3.5z" />
|
|
92
|
+
<path d="M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16zm7-8A7 7 0 1 1 1 8a7 7 0 0 1 14 0z" />
|
|
93
|
+
</svg>');
|
|
94
|
+
--icon-file: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
|
|
95
|
+
<path d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5z" />
|
|
96
|
+
<path d="M7.646 1.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708L8.5 2.707V11.5a.5.5 0 0 1-1 0V2.707L5.354 4.854a.5.5 0 1 1-.708-.708l3-3z" />
|
|
97
|
+
</svg>');
|
|
98
|
+
--icon-select: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
|
|
99
|
+
<path fill-rule="evenodd" d="M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z" />
|
|
100
|
+
</svg>');
|
|
101
|
+
--icon-radio: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="white" viewBox="0 0 16 16">
|
|
102
|
+
<circle cx="8" cy="8" r="8" />
|
|
103
|
+
</svg>');
|
|
104
|
+
--icon-check: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="white" viewBox="0 0 16 16">
|
|
105
|
+
<path d="M10.97 4.97a.75.75 0 0 1 1.07 1.05l-3.99 4.99a.75.75 0 0 1-1.08.02L4.324 8.384a.75.75 0 1 1 1.06-1.06l2.094 2.093 3.473-4.425a.267.267 0 0 1 .02-.022z" />
|
|
106
|
+
</svg>');
|
|
93
107
|
--icon-switch: var(--icon-radio);
|
|
94
108
|
|
|
95
109
|
}
|
|
@@ -102,20 +116,20 @@
|
|
|
102
116
|
// This is the light theme (or if there is none)
|
|
103
117
|
html[data-theme=light],
|
|
104
118
|
html:not([data-theme]) {
|
|
105
|
-
|
|
106
|
-
|
|
119
|
+
--color-body: white;
|
|
120
|
+
--color-font: black;
|
|
107
121
|
}
|
|
108
122
|
|
|
109
123
|
// This is for the dark theme
|
|
110
124
|
html[data-theme=dark] {
|
|
111
|
-
|
|
112
|
-
|
|
125
|
+
--color-body: black;
|
|
126
|
+
--color-font: white;
|
|
113
127
|
}
|
|
114
128
|
|
|
115
129
|
// This is for the dark theme
|
|
116
130
|
html[data-theme=my-custom-theme] {
|
|
117
|
-
|
|
118
|
-
|
|
131
|
+
--color-body: white;
|
|
132
|
+
--color-font: orange;
|
|
119
133
|
}
|
|
120
134
|
</doc-code>
|
|
121
135
|
|
|
@@ -18,7 +18,7 @@ class DocLayout extends HTMLElement {
|
|
|
18
18
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-pin-angle" viewBox="0 0 16 16">
|
|
19
19
|
<path d="M9.828.722a.5.5 0 0 1 .354.146l4.95 4.95a.5.5 0 0 1 0 .707c-.48.48-1.072.588-1.503.588-.177 0-.335-.018-.46-.039l-3.134 3.134a6 6 0 0 1 .16 1.013c.046.702-.032 1.687-.72 2.375a.5.5 0 0 1-.707 0l-2.829-2.828-3.182 3.182c-.195.195-1.219.902-1.414.707s.512-1.22.707-1.414l3.182-3.182-2.828-2.829a.5.5 0 0 1 0-.707c.688-.688 1.673-.767 2.375-.72a6 6 0 0 1 1.013.16l3.134-3.133a3 3 0 0 1-.04-.461c0-.43.108-1.022.589-1.503a.5.5 0 0 1 .353-.146m.122 2.112v-.002zm0-.002v.002a.5.5 0 0 1-.122.51L6.293 6.878a.5.5 0 0 1-.511.12H5.78l-.014-.004a5 5 0 0 0-.288-.076 5 5 0 0 0-.765-.116c-.422-.028-.836.008-1.175.15l5.51 5.509c.141-.34.177-.753.149-1.175a5 5 0 0 0-.192-1.054l-.004-.013v-.001a.5.5 0 0 1 .12-.512l3.536-3.535a.5.5 0 0 1 .532-.115l.096.022c.087.017.208.034.344.034q.172.002.343-.04L9.927 2.028q-.042.172-.04.343a1.8 1.8 0 0 0 .062.46z"/>
|
|
20
20
|
</svg>
|
|
21
|
-
0.1.
|
|
21
|
+
0.1.19
|
|
22
22
|
</span>
|
|
23
23
|
</li>
|
|
24
24
|
<li>
|
package/js/_dialog.js
CHANGED
|
@@ -36,6 +36,8 @@ export default class Dialog extends BaseComponent {
|
|
|
36
36
|
|
|
37
37
|
this._form = this._element.querySelector('form') ?? {}
|
|
38
38
|
|
|
39
|
+
this._previousFocus = null
|
|
40
|
+
|
|
39
41
|
// Init the event listener
|
|
40
42
|
this.#init()
|
|
41
43
|
|
|
@@ -49,7 +51,7 @@ export default class Dialog extends BaseComponent {
|
|
|
49
51
|
#init() {
|
|
50
52
|
|
|
51
53
|
// OPEN
|
|
52
|
-
this._buttons.open.forEach((button) => button.addEventListener('click', () => this.open()))
|
|
54
|
+
this._buttons.open.forEach((button) => button.addEventListener('click', (e) => this.open(e)))
|
|
53
55
|
|
|
54
56
|
// CLOSE
|
|
55
57
|
this._buttons.close.forEach((button) => button.addEventListener('click', () => this.close()))
|
|
@@ -79,7 +81,7 @@ export default class Dialog extends BaseComponent {
|
|
|
79
81
|
* Open the dialog
|
|
80
82
|
*
|
|
81
83
|
*/
|
|
82
|
-
open() {
|
|
84
|
+
open(e) {
|
|
83
85
|
|
|
84
86
|
// Run event before opening, and stop if e.preventDefault()
|
|
85
87
|
const callback = this.emmitEvent('opening')
|
|
@@ -88,6 +90,11 @@ export default class Dialog extends BaseComponent {
|
|
|
88
90
|
// Open the dialog (the methode changed if it's a modal)
|
|
89
91
|
this._isModal ? this._element.showModal() : this._element.show()
|
|
90
92
|
|
|
93
|
+
// If open via an HTML element, keep it as previous to reset the focus
|
|
94
|
+
if (e && e.target instanceof HTMLElement) {
|
|
95
|
+
this._previousFocus = e.target
|
|
96
|
+
}
|
|
97
|
+
|
|
91
98
|
// Toggle the [inert] attribute on the body
|
|
92
99
|
this.#toggleBodyAttribute()
|
|
93
100
|
|
|
@@ -112,6 +119,9 @@ export default class Dialog extends BaseComponent {
|
|
|
112
119
|
// Toggle the [inert] attribute on the body
|
|
113
120
|
this.#toggleBodyAttribute()
|
|
114
121
|
|
|
122
|
+
// Reset the focus on the previous element
|
|
123
|
+
if (this._previousFocus) this._previousFocus.focus()
|
|
124
|
+
|
|
115
125
|
// Run event after closed
|
|
116
126
|
this.emmitEvent('closed')
|
|
117
127
|
|
|
@@ -148,6 +158,9 @@ export default class Dialog extends BaseComponent {
|
|
|
148
158
|
// Toggle the [inert] attribute on the body
|
|
149
159
|
this.#toggleBodyAttribute()
|
|
150
160
|
|
|
161
|
+
// Reset the focus on the previous element
|
|
162
|
+
if (this._previousFocus) this._previousFocus.focus()
|
|
163
|
+
|
|
151
164
|
// Run event after submited
|
|
152
165
|
this.emmitEvent('submited', { form: this._form })
|
|
153
166
|
|
package/js/_drawer.js
CHANGED
|
@@ -45,7 +45,7 @@ export default class Drawer extends BaseComponent {
|
|
|
45
45
|
|
|
46
46
|
this._isOpen = !this._element.hidden
|
|
47
47
|
|
|
48
|
-
this._focus = this._element.querySelector('[tabindex="0"]') ?? this._element.querySelector('a,
|
|
48
|
+
this._focus = this._element.getAttribute('tabindex') === '0' ? this._element : this._element.querySelector('[tabindex="0"]') ?? this._element.querySelector('button, a, input')
|
|
49
49
|
|
|
50
50
|
this._cookie = this._options.cookie ? new Cookie(this._options.cookie) : null
|
|
51
51
|
|
package/js/_dropdown.js
CHANGED
|
@@ -37,7 +37,7 @@ export default class Dropdown extends BaseComponent {
|
|
|
37
37
|
// Define the properties
|
|
38
38
|
this._button = this._element.querySelector('[aria-controls]')
|
|
39
39
|
this._content = document.getElementById(this._button.getAttribute('aria-controls'))
|
|
40
|
-
this._focus = this.
|
|
40
|
+
this._focus = this._content.getAttribute('tabindex') === '0' ? this._content : this._content.querySelector('[tabindex="0"]') ?? this._content.querySelector('button, a, input')
|
|
41
41
|
|
|
42
42
|
// Init the event listener
|
|
43
43
|
this.#init()
|
package/js/_sortable.js
CHANGED
|
@@ -29,7 +29,8 @@ export default class Sortable extends BaseComponent {
|
|
|
29
29
|
this._withHandle = this._element.querySelector('[data-handle=sortable]') ? true : false
|
|
30
30
|
this._current = null
|
|
31
31
|
|
|
32
|
-
//
|
|
32
|
+
// Bind this only one time foreach methods
|
|
33
|
+
// * Because I add and remove events
|
|
33
34
|
this.handleMouseDown = this.handleMouseDown.bind(this)
|
|
34
35
|
this.handleMouseUp = this.handleMouseUp.bind(this)
|
|
35
36
|
this.drag = this.drag.bind(this)
|
|
@@ -74,9 +75,6 @@ export default class Sortable extends BaseComponent {
|
|
|
74
75
|
*/
|
|
75
76
|
#initEvents() {
|
|
76
77
|
|
|
77
|
-
// Get the items
|
|
78
|
-
//this._items = this._element.querySelectorAll('[draggable]')
|
|
79
|
-
|
|
80
78
|
// Add the events
|
|
81
79
|
this._items.forEach(item => {
|
|
82
80
|
item.addEventListener('mousedown', this.handleMouseDown)
|
package/js/_toggle.js
CHANGED
|
@@ -103,7 +103,10 @@ export default class Toggle extends BaseComponent {
|
|
|
103
103
|
// Toggle the [hidden] attribute
|
|
104
104
|
toggable.hidden = this.value !== toggleValue && groupValue !== toggleValue
|
|
105
105
|
|
|
106
|
-
if (!toggable.hidden
|
|
106
|
+
if (!toggable.hidden) {
|
|
107
|
+
const focus = toggable.getAttribute('tabindex') === '0' ? toggable : toggable.querySelector('[tabindex="0"]') ?? toggable.querySelector('button, a, input')
|
|
108
|
+
if (focus) focus.focus()
|
|
109
|
+
}
|
|
107
110
|
|
|
108
111
|
})
|
|
109
112
|
|
package/js/_tree.js
CHANGED
|
@@ -29,7 +29,9 @@ export default class Tree extends BaseComponent {
|
|
|
29
29
|
|
|
30
30
|
this._withHandle = this._type == 'grid' && this._element.querySelector('[data-handle=tree]') ? true : false
|
|
31
31
|
|
|
32
|
-
this
|
|
32
|
+
// Bind this only one time foreach methods
|
|
33
|
+
// * Because I add and remove events
|
|
34
|
+
this.toggle = this.toggle.bind(this)
|
|
33
35
|
|
|
34
36
|
// Init the event listener
|
|
35
37
|
this.#init()
|
|
@@ -43,12 +45,45 @@ export default class Tree extends BaseComponent {
|
|
|
43
45
|
*/
|
|
44
46
|
#init() {
|
|
45
47
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
// Init the events on the items
|
|
49
|
+
this.#initEvents()
|
|
50
|
+
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Get the list of the items
|
|
55
|
+
*
|
|
56
|
+
* @return {object}
|
|
57
|
+
*/
|
|
58
|
+
get _items() {
|
|
59
|
+
return this._element.querySelectorAll('[aria-expanded]')
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Init the items and the event listeners
|
|
64
|
+
*
|
|
65
|
+
* @private
|
|
66
|
+
*/
|
|
67
|
+
#initEvents() {
|
|
68
|
+
this._items.forEach(item => {
|
|
69
|
+
item.addEventListener('click', this.toggle)
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Reset the event listeners
|
|
75
|
+
*
|
|
76
|
+
* @private
|
|
77
|
+
*/
|
|
78
|
+
resetEvents() {
|
|
79
|
+
|
|
80
|
+
// Remove the listeners
|
|
81
|
+
this._items.forEach((item) => {
|
|
82
|
+
item.removeEventListener('click', this.toggle)
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
// Re-initialise the items
|
|
86
|
+
this.#initEvents()
|
|
52
87
|
|
|
53
88
|
}
|
|
54
89
|
|
|
@@ -57,7 +92,21 @@ export default class Tree extends BaseComponent {
|
|
|
57
92
|
*
|
|
58
93
|
* @param {HTMLElement} item - The current item
|
|
59
94
|
*/
|
|
60
|
-
toggle(
|
|
95
|
+
toggle(e) {
|
|
96
|
+
|
|
97
|
+
let item
|
|
98
|
+
|
|
99
|
+
if (e instanceof Event) {
|
|
100
|
+
// If it's an event verify about the handle + if target is an HTML element
|
|
101
|
+
if (!(e.target instanceof Element)) return
|
|
102
|
+
if (this._withHandle && (!e.target.hasAttribute('data-handle') || e.target.getAttribute('data-handle') !== 'tree')) return
|
|
103
|
+
e.stopPropagation()
|
|
104
|
+
item = e.target.closest('[aria-expanded]')
|
|
105
|
+
} else {
|
|
106
|
+
// If it's NOT an event verify that it's an HTML element
|
|
107
|
+
if (!(e instanceof Element)) return
|
|
108
|
+
item = e
|
|
109
|
+
}
|
|
61
110
|
|
|
62
111
|
// Check for errors
|
|
63
112
|
if (!(item instanceof HTMLElement)) throw new Error(ErrorMessage.instanceOf('item', 'HTMLElement'))
|
|
@@ -74,8 +123,36 @@ export default class Tree extends BaseComponent {
|
|
|
74
123
|
|
|
75
124
|
// Set the focus on the required child
|
|
76
125
|
if (!isExpanded) {
|
|
77
|
-
|
|
78
|
-
|
|
126
|
+
|
|
127
|
+
let childToFocus = null
|
|
128
|
+
|
|
129
|
+
const child = children.find(el => {
|
|
130
|
+
|
|
131
|
+
// Check if the child have a tabindex
|
|
132
|
+
if (el.getAttribute('tabindex') === '0') {
|
|
133
|
+
childToFocus = el
|
|
134
|
+
return el
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Otherwise if an element inside the child have the tabindex
|
|
138
|
+
const childWithTabIndex = el.querySelector('[tabindex="0"]')
|
|
139
|
+
if (childWithTabIndex) {
|
|
140
|
+
childToFocus = childWithTabIndex
|
|
141
|
+
return childWithTabIndex
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Otherwise get the first focusable element
|
|
145
|
+
childToFocus = el.querySelector('button, a, input')
|
|
146
|
+
return el
|
|
147
|
+
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
// Add the focus if open
|
|
151
|
+
// * Need to wait the transition before make it focused
|
|
152
|
+
if (child && childToFocus) {
|
|
153
|
+
childToFocus.focus()
|
|
154
|
+
}
|
|
155
|
+
|
|
79
156
|
}
|
|
80
157
|
|
|
81
158
|
// If type grid, collapse the subchildren
|
package/js/tests/drawer.test.js
CHANGED
|
@@ -26,7 +26,7 @@ beforeAll(() => {
|
|
|
26
26
|
document.body.innerHTML =
|
|
27
27
|
'<div id="backdrop"></div>' +
|
|
28
28
|
'<button aria-expanded="false" aria-pressed="false" aria-controls="drawer"></button>' +
|
|
29
|
-
'<aside id="drawer"
|
|
29
|
+
'<aside id="drawer" hidden><button id="focus"></button></aside>'
|
|
30
30
|
|
|
31
31
|
Object.defineProperty(window, 'innerWidth', { configurable: true, value: 1200 })
|
|
32
32
|
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -35,6 +35,9 @@
|
|
|
35
35
|
$default-padding-inline: var(--#{$name}-padding-inline, map.get($properties, padding-inline));
|
|
36
36
|
$default-padding-block: var(--#{$name}-padding-block, map.get($properties, padding-block));
|
|
37
37
|
|
|
38
|
+
$default-hover-background: color-mix(in srgb, $default-background, var(--hover-color) var(--hover-percent));
|
|
39
|
+
$default-active-background: color-mix(in srgb, $default-background, var(--active-color) var(--active-percent));
|
|
40
|
+
|
|
38
41
|
// Define the CSS
|
|
39
42
|
color: $default-color;
|
|
40
43
|
background-color: $default-background;
|
|
@@ -59,23 +62,28 @@
|
|
|
59
62
|
// Define the interactive states
|
|
60
63
|
@if($states !=()) {
|
|
61
64
|
|
|
62
|
-
// State: focus
|
|
63
|
-
@if(list.index($states, 'focus')) {
|
|
64
|
-
&:focus {
|
|
65
|
-
outline: var(--#{$name}-focus-size, var(--focus-size)) var(--#{$name}-focus-style, var(--focus-style)) var(--#{$name}-focus-color, color-mix(in srgb, var(--#{$name}-border-color, var(--#{$name}-background, $default-color)), transparent var(--focus-opacity)));
|
|
66
|
-
outline-offset: var(--#{$name}-focus-offset, var(--focus-offset));
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
65
|
// State: hover
|
|
71
66
|
@if(list.index($states, 'hover')) {
|
|
72
67
|
&:hover {
|
|
73
68
|
color: var(--#{$name}-hover-color, $default-color);
|
|
74
|
-
background-color: var(--#{$name}-hover-background,
|
|
69
|
+
background-color: var(--#{$name}-hover-background, $default-hover-background);
|
|
75
70
|
border-color: var(--#{$name}-hover-border-color, $default-border-color);
|
|
76
71
|
}
|
|
77
72
|
}
|
|
78
73
|
|
|
74
|
+
// State: focus
|
|
75
|
+
@if(list.index($states, 'focus')) {
|
|
76
|
+
|
|
77
|
+
&:focus,
|
|
78
|
+
&:focus-visible {
|
|
79
|
+
color: var(--#{$name}-focus-color, var(--#{$name}-hover-color, $default-color));
|
|
80
|
+
background-color: var(--#{$name}-focus-background, var(--#{$name}-hover-background, $default-hover-background));
|
|
81
|
+
border-color: var(--#{$name}-focus-border-color, var(--#{$name}-hover-border-color, $default-border-color));
|
|
82
|
+
outline: var(--#{$name}-outline-size, var(--outline-size)) var(--#{$name}-outline-style, var(--outline-style)) var(--#{$name}-outline-color, color-mix(in srgb, currentColor, transparent var(--outline-opacity)));
|
|
83
|
+
outline-offset: var(--#{$name}-outline-offset, var(--outline-offset));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
79
87
|
// State: active
|
|
80
88
|
@if(list.index($states, 'active')) {
|
|
81
89
|
|
|
@@ -84,7 +92,7 @@
|
|
|
84
92
|
&[aria-selected=true],
|
|
85
93
|
&[aria-pressed=true] {
|
|
86
94
|
color: var(--#{$name}-active-color, $default-color);
|
|
87
|
-
background-color: var(--#{$name}-active-background,
|
|
95
|
+
background-color: var(--#{$name}-active-background, $default-active-background);
|
|
88
96
|
border-color: var(--#{$name}-active-border-color, $default-border-color);
|
|
89
97
|
}
|
|
90
98
|
}
|
|
@@ -30,9 +30,11 @@ button[role=link] {
|
|
|
30
30
|
color: var(--anchor-hover-color, var(--anchor-color, currentColor));
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
&:focus,
|
|
33
34
|
&:focus-visible {
|
|
34
|
-
|
|
35
|
-
outline
|
|
35
|
+
color: var(--anchor-focus-color, var(--anchor-hover-color, var(--anchor-color, currentColor)));
|
|
36
|
+
outline: var(--anchor-outline-size, var(--outline-size)) var(--anchor-outline-style, var(--outline-style)) var(--anchor-outline-color, color-mix(in srgb, currentColor, transparent var(--outline-opacity)));
|
|
37
|
+
outline-offset: var(--anchor-outline-offset, var(--outline-offset));
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
&:active,
|
package/scss/themes/_root.scss
CHANGED
|
@@ -38,11 +38,11 @@
|
|
|
38
38
|
--border-style: solid;
|
|
39
39
|
--border-radius: .25rem;
|
|
40
40
|
|
|
41
|
-
//
|
|
42
|
-
--
|
|
43
|
-
--
|
|
44
|
-
--
|
|
45
|
-
--
|
|
41
|
+
// Outline (:focus)
|
|
42
|
+
--outline-size: 3px;
|
|
43
|
+
--outline-style: solid;
|
|
44
|
+
--outline-offset: 0;
|
|
45
|
+
--outline-opacity: 50%;
|
|
46
46
|
|
|
47
47
|
// Hover (color-mix)
|
|
48
48
|
--hover-color: black;
|
|
Binary file
|