edu-webcomponents 1.16.1 → 1.19.6

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.
@@ -0,0 +1,50 @@
1
+ name: Release and Publish to npmjs
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ jobs:
9
+ release-and-publish:
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ contents: write
13
+ id-token: write
14
+
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - name: Set up Node
19
+ uses: actions/setup-node@v4
20
+ with:
21
+ node-version: 20
22
+ registry-url: 'https://registry.npmjs.org'
23
+
24
+ - name: Get version from package.json
25
+ id: version
26
+ run: echo "version=$(jq -r .version package.json)" >> $GITHUB_OUTPUT
27
+
28
+ - name: Set up Git
29
+ run: |
30
+ git config user.name "github-actions"
31
+ git config user.email "github-actions@github.com"
32
+
33
+ - name: Create tag
34
+ run: |
35
+ git tag v${{ steps.version.outputs.version }}
36
+ git push origin v${{ steps.version.outputs.version }}
37
+
38
+ - name: Create GitHub Release using gh
39
+ run: |
40
+ gh release create v${{ steps.version.outputs.version }} \
41
+ --title "v${{ steps.version.outputs.version }}" \
42
+ --notes "Release v${{ steps.version.outputs.version }}"
43
+ env:
44
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
45
+
46
+ - run: npm install -g npm
47
+ - run: npm ci
48
+ - run: npm publish --provenance --access public
49
+ env:
50
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/CHANGELOG.md CHANGED
@@ -1,5 +1,41 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 1.19.6 - 2025-08-09
4
+ - Fix released package in GitHub is not published in npm registry
5
+
6
+ ## 1.19.5 - 2025-08-09
7
+ - Fix released package in GitHub is not published in npm registry
8
+
9
+ ## 1.19.4 - 2025-08-09
10
+ - Fix released package in GitHub is not published in npm registry
11
+
12
+ ## 1.19.3 - 2025-08-09
13
+ - Fix released package in GitHub is not published in npm registry
14
+
15
+ ## 1.19.2 - 2025-08-08
16
+ - Make EduTooltip have bottom position as default when the prop is not set or is set with invalid value
17
+
18
+ ## 1.19.1 - 2025-08-07
19
+ - Improve docs for stories of EduProgressBar
20
+
21
+ ## 1.19.0 - 2025-08-06
22
+ - Add EduProgressBar web component
23
+
24
+ ## 1.18.0 - 2025-08-05
25
+ - Add EduTooltip web component
26
+
27
+ ## 1.17.3 - 2025-08-04
28
+ - Update docs
29
+
30
+ ## 1.17.2 - 2025-08-03
31
+ - Make values of colors of EduButton not defined in the component, but as constants accessible by the entire web components catalog
32
+
33
+ ## 1.17.1 - 2025-08-02
34
+ - Format code
35
+
36
+ ## 1.17.0 - 2025-08-02
37
+ - Make releasing and tagging use the version from package.json
38
+
3
39
  ## 1.16.1 - 2025-08-02
4
40
  - Fix versioning of release
5
41
 
@@ -1,4 +1,3 @@
1
1
  # Release and tag to GitHub by using GitHub Actions
2
- Use workflow from [here](https://github.com/marketplace/actions/release-on-merge-action) and:
3
- - Add corresponding inputs
2
+ Use workflow located in .github/workflows/release-packages-to-github.yaml:
4
3
  - Create the needed token and add it to GitHub secrets
package/index.js CHANGED
@@ -1 +1,3 @@
1
1
  export { EduButton } from './src/EduButton.js';
2
+ export { EduProgressBar } from './src/EduProgressBar.js';
3
+ export { EduTooltip } from './src/EduTooltip.js';
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  ],
12
12
  "license": "MIT",
13
13
  "author": "edu-webcomponents",
14
- "version": "1.16.1",
14
+ "version": "1.19.6",
15
15
  "repository": {
16
16
  "type": "git",
17
17
  "url": "https://github.com/eduardocruzpalacios/edu-webcomponents"
package/src/EduButton.js CHANGED
@@ -1,31 +1,35 @@
1
1
  import { html, css, LitElement } from 'lit';
2
+ import { colorsConstants } from './stylesConstants.js';
2
3
 
3
4
  export class EduButton extends LitElement {
4
- static styles = css`
5
- :host {
6
- display: block;
7
- }
8
-
9
- button {
10
- padding: 0.5rem 1rem;
11
- font-size: 1rem;
12
- border: none;
13
- border-radius: 4px;
14
- background-color: #007acc;
15
- color: white;
16
- cursor: pointer;
17
- transition: background-color 0.2s ease-in-out;
18
- }
19
-
20
- button:hover:not(:disabled) {
21
- background-color: #005fa3;
22
- }
23
-
24
- button:disabled {
25
- background-color: #ccc;
26
- cursor: not-allowed;
27
- }
28
- `;
5
+ static styles = [
6
+ colorsConstants,
7
+ css`
8
+ :host {
9
+ display: block;
10
+ }
11
+
12
+ button {
13
+ padding: 0.5rem 1rem;
14
+ font-size: 1rem;
15
+ border: none;
16
+ border-radius: 4px;
17
+ background-color: var(--primary);
18
+ color: var(--primaryForeground);
19
+ cursor: pointer;
20
+ transition: background-color 0.2s ease-in-out;
21
+ }
22
+
23
+ button:hover:not(:disabled) {
24
+ background-color: var(--primaryHover);
25
+ }
26
+
27
+ button:disabled {
28
+ background-color: var(--disabled);
29
+ cursor: not-allowed;
30
+ }
31
+ `,
32
+ ];
29
33
 
30
34
  static properties = {
31
35
  text: { type: String },
@@ -0,0 +1,78 @@
1
+ import { LitElement, html, css } from 'lit';
2
+ import { colorsConstants } from './stylesConstants.js';
3
+
4
+ export class EduProgressBar extends LitElement {
5
+ static properties = {
6
+ value: { type: Number },
7
+ max: { type: Number },
8
+ showLabel: { type: Boolean },
9
+ progressbarName: { type: String },
10
+ };
11
+
12
+ static styles = [
13
+ colorsConstants,
14
+ css`
15
+ :host {
16
+ display: block;
17
+ width: 100%;
18
+ }
19
+ .bar-container {
20
+ position: relative;
21
+ width: 100%;
22
+ height: 20px;
23
+ background-color: var(--greyLight);
24
+ border-radius: 10px;
25
+ overflow: hidden;
26
+ }
27
+ .bar-fill {
28
+ height: 100%;
29
+ background-color: var(--primary);
30
+ transition: width 0.3s ease;
31
+ }
32
+ .label {
33
+ position: absolute;
34
+ top: 0;
35
+ left: 50%;
36
+ transform: translate(-50%, 0);
37
+ height: 100%;
38
+ display: flex;
39
+ align-items: center;
40
+ justify-content: center;
41
+ font-size: 12px;
42
+ font-weight: bold;
43
+ color: var(--blackLight);
44
+ pointer-events: none;
45
+ }
46
+ `,
47
+ ];
48
+
49
+ constructor() {
50
+ super();
51
+ this.value = 0;
52
+ this.max = 100;
53
+ this.progressbarName = 'Progress bar';
54
+ }
55
+
56
+ render() {
57
+ const safeMax = this.max > 0 ? this.max : 100;
58
+ const safeValue = Math.max(0, this.value);
59
+ const percentage = Math.min(100, (safeValue / safeMax) * 100);
60
+ const label = `${Math.round(percentage)}%`;
61
+
62
+ return html`
63
+ <div
64
+ class="bar-container"
65
+ role="progressbar"
66
+ aria-valuemin="0"
67
+ aria-valuemax="${safeMax}"
68
+ aria-valuenow="${Math.min(safeValue, safeMax)}"
69
+ aria-label="${this.progressbarName}"
70
+ >
71
+ <div class="bar-fill" style="width: ${percentage}%"></div>
72
+ ${this.showLabel ? html`<div class="label">${label}</div>` : null}
73
+ </div>
74
+ `;
75
+ }
76
+ }
77
+
78
+ customElements.define('edu-progress-bar', EduProgressBar);
@@ -0,0 +1,126 @@
1
+ import { LitElement, html, css } from 'lit';
2
+ import { colorsConstants } from './stylesConstants.js';
3
+
4
+ const POSITION = {
5
+ BOTTOM: 'bottom',
6
+ TOP: 'top',
7
+ LEFT: 'left',
8
+ RIGHT: 'right',
9
+ };
10
+
11
+ function getPositions() {
12
+ return Object.values(POSITION);
13
+ }
14
+
15
+ function isPositionValid(position) {
16
+ return getPositions().includes(position.toLowerCase());
17
+ }
18
+
19
+ export class EduTooltip extends LitElement {
20
+ static properties = {
21
+ text: { type: String },
22
+ position: { type: String },
23
+ visible: { type: Boolean, reflect: true },
24
+ };
25
+
26
+ constructor() {
27
+ super();
28
+ this._tooltipId = `tooltip-${Math.random().toString(36).slice(2)}`;
29
+ }
30
+
31
+ updated(changedProperties) {
32
+ if (changedProperties.has('position')) {
33
+ if (!isPositionValid(this.position)) {
34
+ this.position = POSITION.BOTTOM;
35
+ }
36
+ }
37
+ }
38
+
39
+ static styles = [
40
+ colorsConstants,
41
+ css`
42
+ :host {
43
+ position: relative;
44
+ display: inline-block;
45
+ }
46
+
47
+ .tooltip {
48
+ position: absolute;
49
+ background-color: var(--blackLight);
50
+ color: var(--primaryForeground);
51
+ padding: 6px 10px;
52
+ border-radius: 4px;
53
+ font-size: 12px;
54
+ white-space: nowrap;
55
+ z-index: 10;
56
+ opacity: 0;
57
+ transition: opacity 0.2s;
58
+ pointer-events: none;
59
+ }
60
+
61
+ :host([visible]) .tooltip {
62
+ opacity: 1;
63
+ }
64
+
65
+ .top {
66
+ bottom: 100%;
67
+ left: 50%;
68
+ transform: translateX(-50%) translateY(-5px);
69
+ }
70
+
71
+ .right {
72
+ top: 50%;
73
+ left: 100%;
74
+ transform: translateX(5px) translateY(-50%);
75
+ }
76
+
77
+ .bottom {
78
+ top: 100%;
79
+ left: 50%;
80
+ transform: translateX(-50%) translateY(5px);
81
+ }
82
+
83
+ .left {
84
+ top: 50%;
85
+ left: auto;
86
+ right: 100%;
87
+ transform: translateX(-5px) translateY(-50%);
88
+ }
89
+ `,
90
+ ];
91
+
92
+ render() {
93
+ const positionClass = this.position
94
+ ? this.position.toLocaleLowerCase()
95
+ : POSITION.BOTTOM;
96
+ return html`
97
+ <span
98
+ tabindex="0"
99
+ aria-describedby=${this._tooltipId}
100
+ @mouseenter=${this._show}
101
+ @mouseleave=${this._hide}
102
+ @focus=${this._show}
103
+ @blur=${this._hide}
104
+ >
105
+ <slot></slot>
106
+ </span>
107
+ <div
108
+ id=${this._tooltipId}
109
+ class="tooltip ${positionClass}"
110
+ role="tooltip"
111
+ >
112
+ ${this.text}
113
+ </div>
114
+ `;
115
+ }
116
+
117
+ _show() {
118
+ this.visible = true;
119
+ }
120
+
121
+ _hide() {
122
+ this.visible = false;
123
+ }
124
+ }
125
+
126
+ customElements.define('edu-tooltip', EduTooltip);
@@ -0,0 +1,102 @@
1
+ import { html } from 'lit';
2
+ import '../EduProgressBar.js';
3
+
4
+ export default {
5
+ title: 'Edu web components/EduProgressBar',
6
+ tags: ['autodocs'],
7
+ render: ({ value, max, showLabel }) =>
8
+ html`<edu-progress-bar
9
+ .value=${value}
10
+ .max=${max}
11
+ ?showLabel=${showLabel}
12
+ ></edu-progress-bar>`,
13
+ argTypes: {
14
+ value: {
15
+ value: 'number',
16
+ description: 'Sets the percentage to which the progress bar is filled in',
17
+ name: 'value',
18
+ },
19
+ max: {
20
+ value: 'number',
21
+ description: 'Sets the value to which the percentage is calculated',
22
+ name: 'max',
23
+ },
24
+ showLabel: {
25
+ value: 'boolean',
26
+ description: 'Shows label of percentage filled in',
27
+ name: 'showLabel',
28
+ },
29
+ },
30
+ args: {
31
+ value: 0,
32
+ max: 100,
33
+ showLabel: false,
34
+ },
35
+ };
36
+
37
+ export const EduProgressBarDefault = {
38
+ args: {},
39
+ };
40
+
41
+ export const EduProgressBar25 = {
42
+ args: {
43
+ value: 25,
44
+ },
45
+ };
46
+ export const EduProgressBar50 = {
47
+ args: {
48
+ value: 50,
49
+ },
50
+ };
51
+ export const EduProgressBar50WithMaxChanged = {
52
+ args: {
53
+ value: 25,
54
+ max: 50,
55
+ },
56
+ };
57
+ export const EduProgressBar75 = {
58
+ args: {
59
+ value: 75,
60
+ },
61
+ };
62
+ export const EduProgressBar100 = {
63
+ args: {
64
+ value: 100,
65
+ },
66
+ };
67
+
68
+ export const EduProgressBarWithLabel = {
69
+ args: { showLabel: true },
70
+ };
71
+
72
+ export const EduProgressBar25WithLabel = {
73
+ args: {
74
+ value: 25,
75
+ showLabel: true,
76
+ },
77
+ };
78
+ export const EduProgressBar50WithLabel = {
79
+ args: {
80
+ value: 50,
81
+ showLabel: true,
82
+ },
83
+ };
84
+ export const EduProgressBar50WithLabelAndMaxChanged = {
85
+ args: {
86
+ value: 25,
87
+ max: 50,
88
+ showLabel: true,
89
+ },
90
+ };
91
+ export const EduProgressBar75WithLabel = {
92
+ args: {
93
+ value: 75,
94
+ showLabel: true,
95
+ },
96
+ };
97
+ export const EduProgressBar100WithLabel = {
98
+ args: {
99
+ value: 100,
100
+ showLabel: true,
101
+ },
102
+ };
@@ -0,0 +1,68 @@
1
+ import { html } from 'lit';
2
+ import '../EduTooltip.js';
3
+
4
+ export default {
5
+ title: 'Edu web components/EduTooltip',
6
+ tags: ['autodocs'],
7
+ render: ({ text, position }) =>
8
+ html`<edu-tooltip .text=${text} .position=${position}
9
+ ><p>Hello, place the mouse over this text</p></edu-tooltip
10
+ >`,
11
+ argTypes: {
12
+ text: {
13
+ control: 'text',
14
+ description: 'Overwritten button text',
15
+ name: 'text',
16
+ },
17
+ position: {
18
+ control: 'text',
19
+ description:
20
+ 'Position of the tooltip respect to the element making it visible: top / bottom / left / right',
21
+ name: 'position',
22
+ },
23
+ },
24
+ args: {
25
+ text: 'Custom text',
26
+ position: '',
27
+ },
28
+ };
29
+
30
+ export const EduTooltipDefaultPositionBottom = {
31
+ args: {},
32
+ };
33
+
34
+ export const EduTooltipInvalidPositionPropBottom = {
35
+ args: {
36
+ position: 'Edu',
37
+ },
38
+ };
39
+
40
+ export const EduTooltipPositionBottom = {
41
+ args: {
42
+ position: 'bottom',
43
+ },
44
+ };
45
+
46
+ export const EduTooltipPositionTop = {
47
+ args: {
48
+ position: 'top',
49
+ },
50
+ };
51
+
52
+ export const EduTooltipPositionRight = {
53
+ args: {
54
+ position: 'right',
55
+ },
56
+ };
57
+
58
+ export const EduTooltipPositionLeft = {
59
+ args: {
60
+ position: 'left',
61
+ },
62
+ };
63
+
64
+ export const EduTooltipPositionLeftCaseInsensitive = {
65
+ args: {
66
+ position: 'LEFT',
67
+ },
68
+ };
@@ -0,0 +1,15 @@
1
+ import { css } from 'lit';
2
+
3
+ export const colorsConstants = css`
4
+ :host {
5
+ --primary: #007acc;
6
+ --primaryHover: #005fa3;
7
+ --primaryForeground: #fff;
8
+
9
+ --blackLight: #333;
10
+
11
+ --greyLight: #eee;
12
+
13
+ --disabled: #ccc;
14
+ }
15
+ `;
@@ -0,0 +1,173 @@
1
+ // test/edu-progress-bar.test.js
2
+ import { html, fixture, expect } from '@open-wc/testing';
3
+ import '../src/EduProgressBar.js'; // ajusta la ruta si es necesario
4
+
5
+ describe('EduProgressBar', () => {
6
+ it('renders with default values', async () => {
7
+ const el = await fixture(html`<edu-progress-bar></edu-progress-bar>`);
8
+
9
+ const bar = el.shadowRoot.querySelector('.bar-fill');
10
+ const label = el.shadowRoot.querySelector('.label');
11
+
12
+ expect(el.value).to.equal(0);
13
+ expect(el.max).to.equal(100);
14
+ expect(bar.style.width).to.equal('0%');
15
+ expect(label).to.be.null;
16
+ });
17
+
18
+ it('renders with default values (with label)', async () => {
19
+ const el = await fixture(
20
+ html`<edu-progress-bar .showLabel=${true}></edu-progress-bar>`,
21
+ );
22
+
23
+ const bar = el.shadowRoot.querySelector('.bar-fill');
24
+ const label = el.shadowRoot.querySelector('.label');
25
+
26
+ expect(el.value).to.equal(0);
27
+ expect(el.max).to.equal(100);
28
+ expect(bar.style.width).to.equal('0%');
29
+ expect(label.textContent).to.equal('0%');
30
+ });
31
+
32
+ it('calculates percentage correctly', async () => {
33
+ const el = await fixture(
34
+ html`<edu-progress-bar .value=${25} .max=${50}></edu-progress-bar>`,
35
+ );
36
+
37
+ const bar = el.shadowRoot.querySelector('.bar-fill');
38
+ const label = el.shadowRoot.querySelector('.label');
39
+
40
+ expect(bar.style.width).to.equal('50%');
41
+ expect(label).to.be.null;
42
+ });
43
+
44
+ it('calculates percentage correctly (with label)', async () => {
45
+ const el = await fixture(
46
+ html`<edu-progress-bar
47
+ .value=${25}
48
+ .max=${50}
49
+ .showLabel=${true}
50
+ ></edu-progress-bar>`,
51
+ );
52
+
53
+ const bar = el.shadowRoot.querySelector('.bar-fill');
54
+ const label = el.shadowRoot.querySelector('.label');
55
+
56
+ expect(bar.style.width).to.equal('50%');
57
+ expect(label.textContent).to.equal('50%');
58
+ });
59
+
60
+ it('caps percentage at 100%', async () => {
61
+ const el = await fixture(
62
+ html`<edu-progress-bar .value=${200} .max=${100}></edu-progress-bar>`,
63
+ );
64
+ const bar = el.shadowRoot.querySelector('.bar-fill');
65
+ const label = el.shadowRoot.querySelector('.label');
66
+
67
+ expect(bar.style.width).to.equal('100%');
68
+ expect(label).to.be.null;
69
+ });
70
+
71
+ it('caps percentage at 100% (with label)', async () => {
72
+ const el = await fixture(
73
+ html`<edu-progress-bar
74
+ .value=${200}
75
+ .max=${100}
76
+ .showLabel=${true}
77
+ ></edu-progress-bar>`,
78
+ );
79
+
80
+ const bar = el.shadowRoot.querySelector('.bar-fill');
81
+ const label = el.shadowRoot.querySelector('.label');
82
+
83
+ expect(bar.style.width).to.equal('100%');
84
+ expect(label.textContent).to.equal('100%');
85
+ });
86
+
87
+ it('handles invalid max', async () => {
88
+ const el = await fixture(
89
+ html`<edu-progress-bar .value=${50} .max=${0}></edu-progress-bar>`,
90
+ );
91
+
92
+ const bar = el.shadowRoot.querySelector('.bar-fill');
93
+ const label = el.shadowRoot.querySelector('.label');
94
+
95
+ expect(bar.style.width).to.equal('50%');
96
+ expect(label).to.be.null;
97
+ });
98
+
99
+ it('handles invalid max (with label)', async () => {
100
+ const el = await fixture(
101
+ html`<edu-progress-bar
102
+ .value=${50}
103
+ .max=${0}
104
+ .showLabel=${true}
105
+ ></edu-progress-bar>`,
106
+ );
107
+
108
+ const bar = el.shadowRoot.querySelector('.bar-fill');
109
+ const label = el.shadowRoot.querySelector('.label');
110
+
111
+ expect(bar.style.width).to.equal('50%');
112
+ expect(label.textContent).to.equal('50%');
113
+ });
114
+
115
+ it('hides label when showLabel is false', async () => {
116
+ const el = await fixture(
117
+ html`<edu-progress-bar
118
+ .value=${50}
119
+ .showLabel=${false}
120
+ ></edu-progress-bar>`,
121
+ );
122
+
123
+ const label = el.shadowRoot.querySelector('.label');
124
+
125
+ expect(label).to.equal(null);
126
+ });
127
+
128
+ it('shows label when showLabel is true', async () => {
129
+ const el = await fixture(
130
+ html`<edu-progress-bar
131
+ .value=${50}
132
+ .showLabel=${true}
133
+ ></edu-progress-bar>`,
134
+ );
135
+
136
+ const label = el.shadowRoot.querySelector('.label');
137
+
138
+ expect(label).to.exist;
139
+ });
140
+
141
+ it('is accessible by default', async () => {
142
+ const el = await fixture(html`<edu-progress-bar></edu-progress-bar>`);
143
+
144
+ await expect(el).to.be.accessible();
145
+ });
146
+
147
+ it('is accessible by default (with value)', async () => {
148
+ const el = await fixture(
149
+ html`<edu-progress-bar .value=${50}></edu-progress-bar>`,
150
+ );
151
+
152
+ await expect(el).to.be.accessible();
153
+ });
154
+
155
+ it('is accessible (with label)', async () => {
156
+ const el = await fixture(
157
+ html`<edu-progress-bar .showLabel=${true}></edu-progress-bar>`,
158
+ );
159
+
160
+ await expect(el).to.be.accessible();
161
+ });
162
+
163
+ it('is accessible (with value and label)', async () => {
164
+ const el = await fixture(
165
+ html`<edu-progress-bar
166
+ .value=${50}
167
+ .showLabel=${true}
168
+ ></edu-progress-bar>`,
169
+ );
170
+
171
+ await expect(el).to.be.accessible();
172
+ });
173
+ });
@@ -0,0 +1,119 @@
1
+ import { fixture, html, expect } from '@open-wc/testing';
2
+ import '../src/EduTooltip.js';
3
+
4
+ describe('EduTooltip', () => {
5
+ it('is not visible by default', async () => {
6
+ const el = await fixture(html`<edu-tooltip></edu-tooltip>`);
7
+
8
+ const tooltip = el.shadowRoot.querySelector('.tooltip');
9
+ const styles = getComputedStyle(tooltip);
10
+ expect(styles.opacity).to.equal('0');
11
+ });
12
+
13
+ it('sets bottom styles for position when there is not value passed in', async () => {
14
+ const el = await fixture(html`<edu-tooltip></edu-tooltip>`);
15
+
16
+ const tooltip = el.shadowRoot.querySelector('.tooltip');
17
+ expect(tooltip.classList.contains('bottom')).to.be.true;
18
+ });
19
+
20
+ it('sets bottom styles for position when the value passed is not valid', async () => {
21
+ const el = await fixture(
22
+ html`<edu-tooltip position="invalidString"></edu-tooltip>`,
23
+ );
24
+
25
+ const tooltip = el.shadowRoot.querySelector('.tooltip');
26
+ expect(tooltip.classList.contains('bottom')).to.be.true;
27
+ });
28
+
29
+ it('applies class for position', async () => {
30
+ const el = await fixture(
31
+ html`<edu-tooltip position="right"></edu-tooltip>`,
32
+ );
33
+
34
+ const tooltip = el.shadowRoot.querySelector('.tooltip');
35
+ expect(tooltip.classList.contains('right')).to.be.true;
36
+ });
37
+
38
+ it('applies class for position (case insensitive)', async () => {
39
+ const el = await fixture(
40
+ html`<edu-tooltip position="RIGHT"></edu-tooltip>`,
41
+ );
42
+
43
+ const tooltip = el.shadowRoot.querySelector('.tooltip');
44
+ expect(tooltip.classList.contains('right')).to.be.true;
45
+ });
46
+
47
+ it('renders text of the tooltip', async () => {
48
+ const el = await fixture(html`<edu-tooltip text="Help"></edu-tooltip>`);
49
+
50
+ const tooltip = el.shadowRoot.querySelector('.tooltip');
51
+ expect(tooltip.textContent).to.equal('\n Help\n ');
52
+ });
53
+
54
+ it('shows tooltip when mouseenter event', async () => {
55
+ const el = await fixture(
56
+ html`<edu-tooltip text="Text"><span>Hover me</span></edu-tooltip>`,
57
+ );
58
+
59
+ const trigger = el.shadowRoot.querySelector('span');
60
+ const tooltip = el.shadowRoot.querySelector('.tooltip');
61
+ trigger.dispatchEvent(new Event('mouseenter'));
62
+ await el.updateComplete;
63
+
64
+ const styles = getComputedStyle(tooltip);
65
+ expect(styles.opacity).to.equal('1');
66
+ });
67
+
68
+ it('hides tooltip when mouseleave event', async () => {
69
+ const el = await fixture(
70
+ html`<edu-tooltip text="Text"><span>Hover me</span></edu-tooltip>`,
71
+ );
72
+
73
+ const trigger = el.shadowRoot.querySelector('span');
74
+ const tooltip = el.shadowRoot.querySelector('.tooltip');
75
+ el.visible = true;
76
+ trigger.dispatchEvent(new Event('mouseleave'));
77
+ await el.updateComplete;
78
+
79
+ const styles = getComputedStyle(tooltip);
80
+ expect(styles.opacity).to.equal('0');
81
+ });
82
+
83
+ it('shows tooltip when focus event', async () => {
84
+ const el = await fixture(
85
+ html`<edu-tooltip text="Text"><span>Focus</span></edu-tooltip>`,
86
+ );
87
+
88
+ const trigger = el.shadowRoot.querySelector('span');
89
+ const tooltip = el.shadowRoot.querySelector('.tooltip');
90
+ trigger.dispatchEvent(new Event('focus'));
91
+ await el.updateComplete;
92
+
93
+ const styles = getComputedStyle(tooltip);
94
+ expect(styles.opacity).to.equal('1');
95
+ });
96
+
97
+ it('hides tooltip when blur event', async () => {
98
+ const el = await fixture(
99
+ html`<edu-tooltip text="Text"><span>Focus</span></edu-tooltip>`,
100
+ );
101
+
102
+ const trigger = el.shadowRoot.querySelector('span');
103
+ const tooltip = el.shadowRoot.querySelector('.tooltip');
104
+ el.visible = true;
105
+ trigger.dispatchEvent(new Event('blur'));
106
+ await el.updateComplete;
107
+
108
+ const styles = getComputedStyle(tooltip);
109
+ expect(styles.opacity).to.equal('0');
110
+ });
111
+
112
+ it('is accessible', async () => {
113
+ const el = await fixture(
114
+ html`<edu-tooltip text="Text"><span>Trigger</span></edu-tooltip>`,
115
+ );
116
+
117
+ await expect(el).to.be.accessible();
118
+ });
119
+ });
@@ -1,21 +0,0 @@
1
- name: Publish Package to npmjs
2
- on:
3
- release:
4
- types: [published]
5
- jobs:
6
- build:
7
- runs-on: ubuntu-latest
8
- permissions:
9
- contents: read
10
- id-token: write
11
- steps:
12
- - uses: actions/checkout@v4
13
- - uses: actions/setup-node@v4
14
- with:
15
- node-version: '20.x'
16
- registry-url: 'https://registry.npmjs.org'
17
- - run: npm install -g npm
18
- - run: npm ci
19
- - run: npm publish --provenance --access public
20
- env:
21
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -1,19 +0,0 @@
1
- on:
2
- push:
3
- branches:
4
- - main
5
-
6
- jobs:
7
- release-on-merge:
8
- runs-on: ubuntu-latest
9
- permissions:
10
- contents: write
11
- env:
12
- GITHUB_TOKEN: ${{ secrets.RELEASE }}
13
- steps:
14
- - name: release
15
- uses: dexwritescode/release-on-merge-action@v1
16
- with:
17
- version-increment-strategy: patch
18
- initial-version: '1.16.0'
19
- tag-prefix: v