edu-webcomponents 1.24.0 โ 1.26.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/CHANGELOG.md +16 -1
- package/README.md +25 -0
- package/package.json +1 -1
- package/src/edu-button/src/EduButton.js +15 -4
- package/src/edu-button/test/EduButton.test.js +1 -1
- package/src/edu-loading-spinner/src/EduLoadingSpinner.js +1 -1
- package/src/edu-progress-bar/src/EduProgressBar.js +11 -4
- package/src/edu-skeleton-text/src/EduSkeletonText.js +34 -25
- package/src/edu-tooltip/src/EduTooltip.js +2 -4
- package/src/stylesConstants.js +27 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,9 +4,24 @@ All notable changes to this project will be documented in this file. Dates are d
|
|
|
4
4
|
|
|
5
5
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
6
6
|
|
|
7
|
+
#### [v1.26.0](https://github.com/eduardocruzpalacios/edu-webcomponents/compare/v1.25.0...v1.26.0)
|
|
8
|
+
|
|
9
|
+
- feat: improve accessibility of EduButton according to 2.5.5 in WCAG 2.1 and 2.4.7 in WCAG 2.2 [`969a143`](https://github.com/eduardocruzpalacios/edu-webcomponents/commit/969a143fee573fcb0d93072de73a143a2e2116b6)
|
|
10
|
+
- refactor: code [`65c723d`](https://github.com/eduardocruzpalacios/edu-webcomponents/commit/65c723dc344e9b8bb9da515b76e465c21eab3097)
|
|
11
|
+
|
|
12
|
+
#### [v1.25.0](https://github.com/eduardocruzpalacios/edu-webcomponents/compare/v1.24.0...v1.25.0)
|
|
13
|
+
|
|
14
|
+
> 11 January 2026
|
|
15
|
+
|
|
16
|
+
- feat: implement dark mode [`a5470d0`](https://github.com/eduardocruzpalacios/edu-webcomponents/commit/a5470d0e3d7428ae6084dc3a1c4389ab4223517e)
|
|
17
|
+
- chore: release v1.25.0 [`3e2bbc7`](https://github.com/eduardocruzpalacios/edu-webcomponents/commit/3e2bbc709607880488b421e48d3dc353d7870034)
|
|
18
|
+
|
|
7
19
|
#### [v1.24.0](https://github.com/eduardocruzpalacios/edu-webcomponents/compare/v1.23.0...v1.24.0)
|
|
8
20
|
|
|
9
|
-
|
|
21
|
+
> 9 January 2026
|
|
22
|
+
|
|
23
|
+
- docs: improve README.md [`9300008`](https://github.com/eduardocruzpalacios/edu-webcomponents/commit/9300008a5fe9dedd24bc8b2ee39b663d01b9ef85)
|
|
24
|
+
- chore: release v1.24.0 [`c66fe45`](https://github.com/eduardocruzpalacios/edu-webcomponents/commit/c66fe45ca3b150cb62126dfbd102b2244f59802b)
|
|
10
25
|
|
|
11
26
|
#### [v1.23.0](https://github.com/eduardocruzpalacios/edu-webcomponents/compare/v1.22.0...v1.23.0)
|
|
12
27
|
|
package/README.md
CHANGED
|
@@ -14,6 +14,7 @@ A modern, lightweight collection of reusable web components built with [Lit](htt
|
|
|
14
14
|
- โฟ **Accessible** - ARIA-compliant components with keyboard support
|
|
15
15
|
- ๐ฏ **Framework-agnostic** - Works with any JavaScript framework or vanilla JS
|
|
16
16
|
- ๐จ **Customizable** - CSS custom properties for easy theming
|
|
17
|
+
- ๐ **Dark mode support** - Automatic theme switching with `@media (prefers-color-scheme: dark)`
|
|
17
18
|
- ๐ฆ **Tree-shakeable** - Import only what you need
|
|
18
19
|
- โ
**Well-tested** - Comprehensive test coverage
|
|
19
20
|
|
|
@@ -261,9 +262,33 @@ Components use CSS custom properties for easy theming. Override these in your CS
|
|
|
261
262
|
--greyLight: #e0e0e0;
|
|
262
263
|
--greyDark: #757575;
|
|
263
264
|
--blackLight: #424242;
|
|
265
|
+
--skeletonBase: #e0e0e0;
|
|
266
|
+
--skeletonHighlight: #f0f0f0;
|
|
264
267
|
}
|
|
265
268
|
```
|
|
266
269
|
|
|
270
|
+
### ๐ Dark Mode Support
|
|
271
|
+
|
|
272
|
+
All components automatically support dark mode via `@media (prefers-color-scheme: dark)`. When your operating system or browser is set to dark mode, the components will automatically adapt with optimized color schemes:
|
|
273
|
+
|
|
274
|
+
```css
|
|
275
|
+
@media (prefers-color-scheme: dark) {
|
|
276
|
+
:host {
|
|
277
|
+
--primary: #4db8ff;
|
|
278
|
+
--primaryHover: #66c2ff;
|
|
279
|
+
--primaryForeground: #000;
|
|
280
|
+
--blackLight: #e0e0e0;
|
|
281
|
+
--greyLight: #3d3d3d;
|
|
282
|
+
--greyDark: #666;
|
|
283
|
+
--disabled: #555;
|
|
284
|
+
--skeletonBase: #3d3d3d;
|
|
285
|
+
--skeletonHighlight: #4d4d4d;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
No additional configuration required - dark mode works out of the box!
|
|
291
|
+
|
|
267
292
|
## ๐งช Development
|
|
268
293
|
|
|
269
294
|
### Local Demo
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { html, css, LitElement } from 'lit';
|
|
2
|
-
import { colorsConstants } from '../../stylesConstants.js';
|
|
2
|
+
import { colorsConstants, typographyConstants } from '../../stylesConstants.js';
|
|
3
3
|
|
|
4
4
|
export class EduButton extends LitElement {
|
|
5
5
|
static styles = [
|
|
6
6
|
colorsConstants,
|
|
7
|
+
typographyConstants,
|
|
7
8
|
css`
|
|
8
9
|
:host {
|
|
9
10
|
display: block;
|
|
@@ -18,12 +19,21 @@ export class EduButton extends LitElement {
|
|
|
18
19
|
color: var(--primaryForeground);
|
|
19
20
|
cursor: pointer;
|
|
20
21
|
transition: background-color 0.2s ease-in-out;
|
|
22
|
+
font-family: inherit;
|
|
23
|
+
line-height: var(--lineHeight);
|
|
24
|
+
min-height: 44px;
|
|
25
|
+
min-width: 44px;
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
button:hover:not(:disabled) {
|
|
24
29
|
background-color: var(--primaryHover);
|
|
25
30
|
}
|
|
26
31
|
|
|
32
|
+
button:focus-visible {
|
|
33
|
+
outline: 2px solid var(--primary);
|
|
34
|
+
outline-offset: 2px;
|
|
35
|
+
}
|
|
36
|
+
|
|
27
37
|
button:disabled {
|
|
28
38
|
background-color: var(--disabled);
|
|
29
39
|
cursor: not-allowed;
|
|
@@ -42,15 +52,16 @@ export class EduButton extends LitElement {
|
|
|
42
52
|
super();
|
|
43
53
|
this.text = 'Default text';
|
|
44
54
|
this.type = 'button';
|
|
45
|
-
this.ariaLabel =
|
|
55
|
+
this.ariaLabel = '';
|
|
46
56
|
}
|
|
47
57
|
|
|
48
58
|
render() {
|
|
49
59
|
return html`
|
|
50
60
|
<button
|
|
51
61
|
type=${this.type}
|
|
52
|
-
aria-label=${this.ariaLabel}
|
|
62
|
+
aria-label=${this.ariaLabel || this.text}
|
|
53
63
|
?disabled=${this.disabled}
|
|
64
|
+
aria-disabled=${this.disabled ? 'true' : 'false'}
|
|
54
65
|
>
|
|
55
66
|
${this.text}
|
|
56
67
|
</button>
|
|
@@ -58,4 +69,4 @@ export class EduButton extends LitElement {
|
|
|
58
69
|
}
|
|
59
70
|
}
|
|
60
71
|
|
|
61
|
-
|
|
72
|
+
customElements.define('edu-button', EduButton);
|
|
@@ -45,7 +45,7 @@ describe('EduButton', () => {
|
|
|
45
45
|
expect(button.getAttribute('aria-label')).to.equal(textDefault);
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
-
it('allows overriding aria-label via
|
|
48
|
+
it('allows overriding aria-label via ariaLabel property', async () => {
|
|
49
49
|
const ariaLabel = 'Custom label';
|
|
50
50
|
const el = await fixture(
|
|
51
51
|
html`<edu-button aria-label=${ariaLabel}></edu-button>`
|
|
@@ -53,10 +53,14 @@ export class EduProgressBar extends LitElement {
|
|
|
53
53
|
this.progressbarName = 'Progress bar';
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
_calculatePercentage() {
|
|
57
57
|
const safeMax = this.max > 0 ? this.max : 100;
|
|
58
58
|
const safeValue = Math.max(0, this.value);
|
|
59
|
-
|
|
59
|
+
return Math.min(100, (safeValue / safeMax) * 100);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
render() {
|
|
63
|
+
const percentage = this._calculatePercentage();
|
|
60
64
|
const label = `${Math.round(percentage)}%`;
|
|
61
65
|
|
|
62
66
|
return html`
|
|
@@ -64,8 +68,11 @@ export class EduProgressBar extends LitElement {
|
|
|
64
68
|
class="bar-container"
|
|
65
69
|
role="progressbar"
|
|
66
70
|
aria-valuemin="0"
|
|
67
|
-
aria-valuemax="${
|
|
68
|
-
aria-valuenow="${Math.min(
|
|
71
|
+
aria-valuemax="${this.max > 0 ? this.max : 100}"
|
|
72
|
+
aria-valuenow="${Math.min(
|
|
73
|
+
Math.max(0, this.value),
|
|
74
|
+
this.max > 0 ? this.max : 100
|
|
75
|
+
)}"
|
|
69
76
|
aria-label="${this.progressbarName}"
|
|
70
77
|
>
|
|
71
78
|
<div class="bar-fill" style="width: ${percentage}%"></div>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LitElement, html, css } from 'lit';
|
|
2
|
+
import { colorsConstants } from '../../stylesConstants.js';
|
|
2
3
|
|
|
3
4
|
export class EduSkeletonText extends LitElement {
|
|
4
5
|
static properties = {
|
|
@@ -14,34 +15,42 @@ export class EduSkeletonText extends LitElement {
|
|
|
14
15
|
this.lines = 1;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
static styles =
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
.line {
|
|
24
|
-
border-radius: 4px;
|
|
25
|
-
background: linear-gradient(90deg, #e0e0e0 25%, #f0f0f0 37%, #e0e0e0 63%);
|
|
26
|
-
background-size: 400% 100%;
|
|
27
|
-
animation: shimmer 1.4s ease infinite;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
@keyframes shimmer {
|
|
31
|
-
0% {
|
|
32
|
-
background-position: 100% 0;
|
|
18
|
+
static styles = [
|
|
19
|
+
colorsConstants,
|
|
20
|
+
css`
|
|
21
|
+
:host {
|
|
22
|
+
display: grid;
|
|
23
|
+
gap: 0.5em;
|
|
33
24
|
}
|
|
34
|
-
100% {
|
|
35
|
-
background-position: -100% 0;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
25
|
|
|
39
|
-
@media (prefers-reduced-motion: reduce) {
|
|
40
26
|
.line {
|
|
41
|
-
|
|
27
|
+
border-radius: 4px;
|
|
28
|
+
background: linear-gradient(
|
|
29
|
+
90deg,
|
|
30
|
+
var(--skeletonBase) 25%,
|
|
31
|
+
var(--skeletonHighlight) 37%,
|
|
32
|
+
var(--skeletonBase) 63%
|
|
33
|
+
);
|
|
34
|
+
background-size: 400% 100%;
|
|
35
|
+
animation: shimmer 1.4s ease infinite;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@keyframes shimmer {
|
|
39
|
+
0% {
|
|
40
|
+
background-position: 100% 0;
|
|
41
|
+
}
|
|
42
|
+
100% {
|
|
43
|
+
background-position: -100% 0;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@media (prefers-reduced-motion: reduce) {
|
|
48
|
+
.line {
|
|
49
|
+
animation: none;
|
|
50
|
+
}
|
|
42
51
|
}
|
|
43
|
-
|
|
44
|
-
|
|
52
|
+
`,
|
|
53
|
+
];
|
|
45
54
|
|
|
46
55
|
render() {
|
|
47
56
|
return html`
|
|
@@ -57,4 +66,4 @@ export class EduSkeletonText extends LitElement {
|
|
|
57
66
|
}
|
|
58
67
|
}
|
|
59
68
|
|
|
60
|
-
|
|
69
|
+
customElements.define('edu-skeleton-text', EduSkeletonText);
|
|
@@ -8,12 +8,10 @@ const POSITION = {
|
|
|
8
8
|
RIGHT: 'right',
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
return Object.values(POSITION);
|
|
13
|
-
}
|
|
11
|
+
const VALID_POSITIONS = Object.values(POSITION);
|
|
14
12
|
|
|
15
13
|
function isPositionValid(position) {
|
|
16
|
-
return
|
|
14
|
+
return VALID_POSITIONS.includes(position.toLowerCase());
|
|
17
15
|
}
|
|
18
16
|
|
|
19
17
|
export class EduTooltip extends LitElement {
|
package/src/stylesConstants.js
CHANGED
|
@@ -12,5 +12,32 @@ export const colorsConstants = css`
|
|
|
12
12
|
--greyDark: #aaa;
|
|
13
13
|
|
|
14
14
|
--disabled: #ccc;
|
|
15
|
+
|
|
16
|
+
--skeletonBase: #e0e0e0;
|
|
17
|
+
--skeletonHighlight: #f0f0f0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@media (prefers-color-scheme: dark) {
|
|
21
|
+
:host {
|
|
22
|
+
--primary: #4db8ff;
|
|
23
|
+
--primaryHover: #66c2ff;
|
|
24
|
+
--primaryForeground: #000;
|
|
25
|
+
|
|
26
|
+
--blackLight: #e0e0e0;
|
|
27
|
+
|
|
28
|
+
--greyLight: #3d3d3d;
|
|
29
|
+
--greyDark: #666;
|
|
30
|
+
|
|
31
|
+
--disabled: #555;
|
|
32
|
+
|
|
33
|
+
--skeletonBase: #3d3d3d;
|
|
34
|
+
--skeletonHighlight: #4d4d4d;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
`;
|
|
38
|
+
|
|
39
|
+
export const typographyConstants = css`
|
|
40
|
+
:host {
|
|
41
|
+
--lineHeight: 1.5;
|
|
15
42
|
}
|
|
16
43
|
`;
|