Compare commits

..

6 Commits

Author SHA1 Message Date
github-actions[bot]
e9090d64b9 Version Packages 2021-04-01 20:01:47 +02:00
Benny Powers
728a205b7b chore: add changeset 2021-04-01 19:44:43 +02:00
Benny Powers
67ba29d45a feat(navigation): add no-redirects attribute
By default, the sidebar nav redirects clicks on category headings to
their first child.

To disable those redirects, override
`_includes/_joiningBlocks/_layoutSidebar/sidebar/20-navigation.njk`
and add the `no-redirects` attribute to the `<rocket-navigation>`
element.
2021-04-01 19:44:43 +02:00
github-actions[bot]
758caffdf9 Version Packages 2021-03-25 07:14:15 +01:00
qa46hx
302227e8a9 feat(search): add variable for border-radius of SearchCombobox 2021-03-24 23:20:56 +01:00
Thomas Allmer
04a31220fb chore: align versions across the mono repo 2021-03-15 21:03:07 +01:00
10 changed files with 100 additions and 35 deletions

View File

@@ -47,3 +47,9 @@ export const headlineConverter = () => html`
```
How it then works is very similar to https://www.11ty.dev/docs/plugins/navigation/
## Sidebar redirects
By default, the sidebar nav redirects clicks on category headings to the first child page in that category.
To disable those redirects, override `_includes/_joiningBlocks/_layoutSidebar/sidebar/20-navigation.njk` and add the `no-redirects` attribute to the `<rocket-navigation>` element.

View File

@@ -38,6 +38,6 @@
"testing"
],
"dependencies": {
"plugins-manager": "^0.2.0"
"plugins-manager": "^0.2.1"
}
}

View File

@@ -43,12 +43,12 @@
"remark"
],
"dependencies": {
"@mdjs/mdjs-preview": "^0.3.1",
"@mdjs/mdjs-story": "^0.1.1",
"@mdjs/mdjs-preview": "^0.3.2",
"@mdjs/mdjs-story": "^0.1.2",
"@types/unist": "^2.0.3",
"es-module-lexer": "^0.3.26",
"github-markdown-css": "^4.0.0",
"plugins-manager": "^0.2.0",
"plugins-manager": "^0.2.1",
"rehype-autolink-headings": "^5.0.1",
"rehype-prism-template": "^0.4.1",
"rehype-raw": "^5.0.0",

View File

@@ -1,5 +1,19 @@
# @rocket/navigation
## 0.2.1
### Patch Changes
- 728a205: feat(navigation): add no-redirects attribute
By default, the sidebar nav redirects clicks on category headings to
their first child.
To disable those redirects, override
\_includes/\_joiningBlocks/\_layoutSidebar/sidebar/20-navigation.njk
and add the no-redirects attribute to the <rocket-navigation>
element.
## 0.2.0
### Minor Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@rocket/navigation",
"version": "0.2.0",
"version": "0.2.1",
"publishConfig": {
"access": "public"
},

View File

@@ -1,3 +1,27 @@
/**
* Debounce a function
* @template {(this: any, ...args: any[]) => void} T
* @param {T} func function
* @param {number} wait time in milliseconds to debounce
* @param {boolean} immediate when true, run immediately and on the leading edge
* @return {T} debounced function
*/
function debounce(func, wait, immediate) {
/** @type {number|undefined} */
let timeout;
return /** @type {typeof func}*/ (function () {
let args = /** @type {Parameters<typeof func>} */ (/** @type {unknown}*/ (arguments));
const later = () => {
timeout = undefined;
if (!immediate) func.apply(this, args);
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(this, args);
});
}
/**
* @typedef {object} NavigationListItem
* @property {HTMLElement} headline
@@ -5,12 +29,17 @@
* @property {number} top
*/
/**
* @element rocket-navigation
* @attr {Boolean} no-redirects - if set, will not redirect to first child of nav category when clicking on category header.
*/
export class RocketNavigation extends HTMLElement {
constructor() {
super();
/** @type NavigationListItem[] */
this.list = [];
this.__scrollHandler = this.__scrollHandler.bind(this);
this.__clickHandler = this.__clickHandler.bind(this);
this.__scrollHandler = debounce(this.__scrollHandler.bind(this), 25, true);
this.__isSetup = false;
}
@@ -20,27 +49,7 @@ export class RocketNavigation extends HTMLElement {
}
this.__isSetup = true;
this.addEventListener('click', ev => {
const el = /** @type {HTMLElement} */ (ev.target);
if (el.classList.contains('anchor')) {
const anchor = /** @type {HTMLAnchorElement} */ (el);
ev.preventDefault();
this.dispatchEvent(new Event('close-overlay', { bubbles: true }));
// wait for closing animation to finish before start scrolling
setTimeout(() => {
const parsedUrl = new URL(anchor.href);
document.location.hash = parsedUrl.hash;
}, 250);
}
const links = el.parentElement?.querySelectorAll('ul a');
if (links && links.length > 1) {
const subLink = /** @type {HTMLAnchorElement} */ (links[1]);
if (!subLink.classList.contains('anchor')) {
ev.preventDefault();
subLink.click();
}
}
});
this.addEventListener('click', this.__clickHandler);
const anchors = /** @type {NodeListOf<HTMLAnchorElement>} */ (this.querySelectorAll(
'li.current a.anchor',
@@ -57,12 +66,41 @@ export class RocketNavigation extends HTMLElement {
}
}
// TODO: debounce
window.addEventListener('scroll', this.__scrollHandler);
window.addEventListener('scroll', this.__scrollHandler, { passive: true });
this.__scrollHandler();
}
/**
* @param {Event} ev
*/
__clickHandler(ev) {
const el = /** @type {HTMLElement} */ (ev.target);
if (el.classList.contains('anchor')) {
const anchor =
el instanceof HTMLAnchorElement
? el
: /** @type{HTMLAnchorElement} */ (el.querySelector('a.anchor'));
ev.preventDefault();
this.dispatchEvent(new Event('close-overlay', { bubbles: true }));
// wait for closing animation to finish before start scrolling
setTimeout(() => {
const parsedUrl = new URL(anchor.href);
document.location.hash = parsedUrl.hash;
}, 250);
}
if (!this.hasAttribute('no-redirects')) {
const links = el.parentElement?.querySelectorAll('ul a');
if (links && links.length > 1) {
const subLink = /** @type {HTMLAnchorElement} */ (links[1]);
if (!subLink.classList.contains('anchor')) {
ev.preventDefault();
subLink.click();
}
}
}
}
__scrollHandler() {
for (const listObj of this.list) {
listObj.top = listObj.headline.getBoundingClientRect().top;

View File

@@ -58,7 +58,8 @@ describe('rocket-navigation', () => {
expect(anchorSpy).to.not.be.called;
});
it('will mark the currently "active" headline in the menu', async () => {
it('will mark the currently "active" headline in the menu', async function () {
this.timeout(5000);
function addBlock(headline, length = 5) {
return html`
<h2 id="${headline}">${headline}</h2>
@@ -96,20 +97,20 @@ describe('rocket-navigation', () => {
}
</style>
`);
await aTimeout(0);
await aTimeout(50);
const anchorLis = wrapper.querySelectorAll('.menu-item.anchor');
expect(anchorLis[0]).to.have.class('current');
expect(anchorLis[1]).to.not.have.class('current');
expect(anchorLis[2]).to.not.have.class('current');
document.querySelector('#middle').scrollIntoView();
await aTimeout(20);
await aTimeout(100);
expect(anchorLis[0]).to.not.have.class('current');
expect(anchorLis[1]).to.have.class('current');
expect(anchorLis[2]).to.not.have.class('current');
document.querySelector('#bottom').scrollIntoView();
await aTimeout(20);
await aTimeout(100);
expect(anchorLis[0]).to.not.have.class('current');
expect(anchorLis[1]).to.not.have.class('current');
expect(anchorLis[2]).to.have.class('current');

View File

@@ -1,5 +1,11 @@
# @rocket/search
## 0.3.2
### Patch Changes
- 302227e: Add variable for border-radius of SearchCombobox
## 0.3.1
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@rocket/search",
"version": "0.3.1",
"version": "0.3.2",
"publishConfig": {
"access": "public"
},

View File

@@ -138,7 +138,7 @@ export class RocketSearchCombobox extends LionCombobox {
display: flex;
border: 1px solid var(--rocket-search-input-border-color, #dfe1e5);
box-shadow: none;
border-radius: 24px;
border-radius: var(--rocket-search-input-border-radius, 24px);
padding: 5px 0;
}