@triptease/tt-navbar 0.0.17 → 0.0.18
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/dist/src/TtNavbar.d.ts +4 -1
- package/dist/src/TtNavbar.js +51 -3
- package/dist/src/TtNavbar.js.map +1 -1
- package/dist/test/tt-navbar.test.js +17 -0
- package/dist/test/tt-navbar.test.js.map +1 -1
- package/dist/web/TtNavbar.js +52 -4
- package/dist/web/TtNavbar.js.map +2 -2
- package/dist/web/index.js +52 -4
- package/dist/web/index.js.map +2 -2
- package/dist/web/styles.js +1 -1
- package/dist/web/triptease-logo.js +1 -1
- package/dist/web/tt-navbar.js +52 -4
- package/dist/web/tt-navbar.js.map +2 -2
- package/package.json +1 -1
- package/src/TtNavbar.ts +57 -2
- package/test/tt-navbar.test.ts +24 -0
package/package.json
CHANGED
package/src/TtNavbar.ts
CHANGED
|
@@ -29,11 +29,66 @@ export class TtNavbar extends LitElement {
|
|
|
29
29
|
@property({ type: String, attribute: 'client-key' })
|
|
30
30
|
clientKey?: string;
|
|
31
31
|
|
|
32
|
+
@queryAll('details')
|
|
33
|
+
protected allDetailsElements!: Array<HTMLDetailsElement>;
|
|
34
|
+
|
|
35
|
+
@queryAll('a')
|
|
36
|
+
protected allNavLinks!: Array<HTMLAnchorElement>;
|
|
37
|
+
|
|
32
38
|
@state()
|
|
33
39
|
private sidebarOpen = true;
|
|
34
40
|
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
protected firstUpdated() {
|
|
42
|
+
this.setActiveState();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/*
|
|
46
|
+
* Set the active state for the current page.
|
|
47
|
+
*
|
|
48
|
+
* This function iterates over all nav links and compares the current URL path with the href of each link.
|
|
49
|
+
* If the current URL path starts with the href of a link, the link is marked as active. If multiple links
|
|
50
|
+
* share the same prefix, the longest prefix is used as it is more specific.
|
|
51
|
+
*
|
|
52
|
+
* Example:
|
|
53
|
+
* - Current URL: /channels/123
|
|
54
|
+
* - Nav links:
|
|
55
|
+
* - /channels
|
|
56
|
+
* - /channels/123
|
|
57
|
+
* - /channels/456
|
|
58
|
+
*
|
|
59
|
+
* Loop 1: currentPath = /channels/123, linkPath = /channels, bestMatch = /channels
|
|
60
|
+
* Loop 2: currentPath = /channels/123, linkPath = /channels/123, bestMatch = /channels/123
|
|
61
|
+
* Loop 3: currentPath = /channels/123, linkPath = /channels/456, bestMatch = /channels/123
|
|
62
|
+
* Result: /channels/123 is marked as active
|
|
63
|
+
*
|
|
64
|
+
*/
|
|
65
|
+
private setActiveState = () => {
|
|
66
|
+
const currentPath = window.location.pathname;
|
|
67
|
+
|
|
68
|
+
let bestMatch: HTMLAnchorElement | undefined;
|
|
69
|
+
let bestMatchLength = 0;
|
|
70
|
+
|
|
71
|
+
for (const link of this.allNavLinks) {
|
|
72
|
+
link.classList.remove('current-page');
|
|
73
|
+
if (link.hasAttribute('aria-current')) {
|
|
74
|
+
link.attributes.removeNamedItem('aria-current');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const linkPath = new URL(link.href).pathname;
|
|
78
|
+
|
|
79
|
+
if (currentPath.startsWith(linkPath)) {
|
|
80
|
+
if (linkPath.length > bestMatchLength) {
|
|
81
|
+
bestMatch = link;
|
|
82
|
+
bestMatchLength = linkPath.length;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (bestMatch) {
|
|
88
|
+
bestMatch.classList.add('current-page');
|
|
89
|
+
bestMatch.setAttribute('aria-current', 'page');
|
|
90
|
+
}
|
|
91
|
+
};
|
|
37
92
|
|
|
38
93
|
private closeAllDetails = (element?: HTMLDetailsElement) => {
|
|
39
94
|
this.allDetailsElements.forEach(detail => {
|
package/test/tt-navbar.test.ts
CHANGED
|
@@ -234,4 +234,28 @@ describe('TtNavbar', () => {
|
|
|
234
234
|
});
|
|
235
235
|
});
|
|
236
236
|
});
|
|
237
|
+
|
|
238
|
+
const URLs = [
|
|
239
|
+
['/', 'Dashboard'],
|
|
240
|
+
['/channels', 'Channels'],
|
|
241
|
+
[`/parity/${CLIENT_KEY}`, 'Parity'],
|
|
242
|
+
[`/parity/${CLIENT_KEY}`, 'Parity'],
|
|
243
|
+
[`/parity/${CLIENT_KEY}/foo`, 'Parity'],
|
|
244
|
+
];
|
|
245
|
+
|
|
246
|
+
URLs.forEach(([route, text]) => {
|
|
247
|
+
it(`should show the current page as active when link is ${route}`, async () => {
|
|
248
|
+
// eslint-disable-next-line no-restricted-globals
|
|
249
|
+
history.pushState({}, '', route); // 👈 mock URL
|
|
250
|
+
|
|
251
|
+
const navbar = await fixture<TtNavbar>(
|
|
252
|
+
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar>`,
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
const anchor = navbar.shadowRoot!.querySelector('a[aria-current="page"]');
|
|
256
|
+
|
|
257
|
+
expect(anchor).to.exist;
|
|
258
|
+
expect(anchor!.textContent).to.include(text);
|
|
259
|
+
});
|
|
260
|
+
});
|
|
237
261
|
});
|