Преглед изворни кода

feat(docs): Scroll TOC item into view

Michael Bromley пре 7 година
родитељ
комит
6f9bc33329
4 измењених фајлова са 34 додато и 8 уклоњено
  1. 3 5
      docs/assets/scripts/main.ts
  2. 17 2
      docs/assets/scripts/toc-highlighter.ts
  3. 13 0
      docs/assets/styles/main.scss
  4. 1 1
      package.json

+ 3 - 5
docs/assets/scripts/main.ts

@@ -18,11 +18,9 @@ document.addEventListener('DOMContentLoaded', () => {
         });
     }
 
-    const toc = document.querySelector('#TableOfContents');
-    if (toc) {
-        const tocHighlighter = new TocHighlighter(toc);
-        tocHighlighter.highlight();
-    }
+    const toc = document.querySelector('#TableOfContents') as HTMLDivElement;
+    const tocHighlighter = new TocHighlighter(toc);
+    tocHighlighter.highlight();
 
     const searchInput = document.querySelector('#searchInput') as HTMLInputElement;
     const searchWidget = new SearchWidget(searchInput);

+ 17 - 2
docs/assets/scripts/toc-highlighter.ts

@@ -3,7 +3,7 @@
  */
 export class TocHighlighter {
 
-    constructor(private tocElement: Element) {}
+    constructor(private tocElement: HTMLElement) {}
 
     highlight() {
         const article = document.querySelector('article');
@@ -42,9 +42,24 @@ export class TocHighlighter {
     }
 
     private highlightItem(id: string) {
-        const tocItem = this.tocElement.querySelector(`[href="#${id}"]`);
+        const tocItem = this.tocElement.querySelector(`[href="#${id}"]`) as HTMLAnchorElement;
         if (tocItem) {
             tocItem.classList.add('active');
         }
+        // ensure the highlighted item is scrolled into view in the TOC menu
+        const padding = 12;
+        const tocHeight = this.tocElement.offsetHeight;
+        const tocScrollTop = this.tocElement.scrollTop;
+        const outOfRangeTop = tocItem.offsetTop < (tocScrollTop + padding);
+        const outofRangeBottom = tocHeight + tocScrollTop < (tocItem.offsetTop + padding);
+        if (outOfRangeTop) {
+            // console.log('¬TOP');
+            this.tocElement.scrollTo({ top: tocItem.offsetTop - (tocItem.offsetHeight) - padding });
+        }
+        if (outofRangeBottom) {
+            // console.log('$BOTTOm');
+            const delta = tocItem.offsetTop - (tocHeight + tocScrollTop);
+            this.tocElement.scrollTo({ top: tocScrollTop + delta + tocItem.offsetHeight + padding });
+        }
     }
 }

+ 13 - 0
docs/assets/styles/main.scss

@@ -147,6 +147,19 @@ ul.contents-list {
     }
     a.active {
         font-weight: bold;
+        position: relative;
+        &::before {
+            content: '';
+            position: absolute;
+            left: -12px;
+            top: 3px;
+            display: block;
+            width: 6px;
+            height: 6px;
+            border-radius: 50%;
+            background-color: $brand-color;
+            opacity: 0.5;
+        }
     }
 }
 

+ 1 - 1
package.json

@@ -2,7 +2,7 @@
   "name": "vendure",
   "version": "0.1.0",
   "scripts": {
-    "docs:watch": "concurrently -n docgen,hugo,webpack \"yarn generate-api-docs && yarn generate-config-docs -w\" \"cd docs && hugo server\" \"cd docs && yarn webpack -w\"",
+    "docs:watch": "concurrently -n docgen,hugo,webpack -c green,blue,cyan \"yarn generate-api-docs && yarn generate-config-docs -w\" \"cd docs && hugo server\" \"cd docs && yarn webpack -w\"",
     "docs:build": "yarn generate-api-docs && yarn generate-config-docs && cd docs && yarn webpack --prod && hugo",
     "generate-gql-types": "ts-node ./codegen/generate-graphql-types.ts",
     "generate-config-docs": "ts-node ./codegen/generate-config-docs.ts",