From c0d6f5e9f76f96e3930f32975469e334d1e0ab2d Mon Sep 17 00:00:00 2001 From: Adam Kudrna Date: Mon, 9 Nov 2020 23:54:07 +0100 Subject: [PATCH] WIP Add table of contents to articles (#5) --- .eslintrc | 3 +- assets/js/table-of-contents.js | 38 +++++++++++++++++ assets/scss/main.scss | 1 + .../06-components/_table-of-contents.scss | 42 +++++++++++++++++++ partials/external/tocbot.hbs | 1 + post.hbs | 12 +++++- 6 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 assets/js/table-of-contents.js create mode 100644 assets/scss/styles/06-components/_table-of-contents.scss create mode 100644 partials/external/tocbot.hbs diff --git a/.eslintrc b/.eslintrc index 88a4cff..6a38321 100644 --- a/.eslintrc +++ b/.eslintrc @@ -5,7 +5,8 @@ }, "globals": { "gtag": false, - "snippetsData": false + "snippetsData": false, + "tocbot": false }, "parserOptions": { "ecmaVersion": 10, diff --git a/assets/js/table-of-contents.js b/assets/js/table-of-contents.js new file mode 100644 index 0000000..1182f2c --- /dev/null +++ b/assets/js/table-of-contents.js @@ -0,0 +1,38 @@ +const TOC_ID = 'obsah'; + +const generateToc = () => { + tocbot.init({ + activeLinkClass: 'is-active', + collapsibleClass: 'is-collapsible', + contentSelector: '.js-table-of-contents-source', + headingSelector: 'h1, h2, h3', + isCollapsedClass: 'is-collapsed', + linkClass: 'table-of-contents__link', + listClass: 'table-of-contents__list', + listItemClass: 'table-of-contents__list__item', + scrollSmooth: false, + tocSelector: `#${TOC_ID}`, + }); + + document.getElementById(TOC_ID).classList.add('table-of-contents--active'); +}; + +const destroyToc = () => { + document.getElementById(TOC_ID).classList.remove('table-of-contents--active'); + tocbot.destroy(); +}; + +const updateToc = () => { + const tocEl = document.getElementById(TOC_ID); + + if (window.getComputedStyle(tocEl).display !== 'none') { + if (!tocEl.innerHTML) { + generateToc(); + } + } else if (tocEl.innerHTML) { + destroyToc(); + } +}; + +window.addEventListener('load', () => updateToc()); +window.addEventListener('resize', () => updateToc()); diff --git a/assets/scss/main.scss b/assets/scss/main.scss index 013bce6..c1bd530 100644 --- a/assets/scss/main.scss +++ b/assets/scss/main.scss @@ -63,6 +63,7 @@ @forward "styles/06-components/members-form"; @forward "styles/06-components/navigation"; @forward "styles/06-components/post-card"; +@forward "styles/06-components/table-of-contents"; @forward "styles/06-components/text-field"; // 7. Editor diff --git a/assets/scss/styles/06-components/_table-of-contents.scss b/assets/scss/styles/06-components/_table-of-contents.scss new file mode 100644 index 0000000..1e07a4d --- /dev/null +++ b/assets/scss/styles/06-components/_table-of-contents.scss @@ -0,0 +1,42 @@ +@use '../../settings/container'; +@use '../../tools/breakpoint'; +@use '../../tools/spacing'; +@use '../../tools/transition'; +@use '../../tools/typography'; + +$_breakpoint: xl; + +.table-of-contents { + @include breakpoint.up($_breakpoint) { + @include transition.add('visibility, opacity'); + + position: sticky; + top: 0; + right: 0; + display: block; + //visibility: hidden; + //opacity: 0; + width: calc((100vw - #{container.$article-width}) / 2); + height: 0; + padding: spacing.of(2) container.$padding-sm; + line-height: typography.line-height(dense); + will-change: visibility, opacity; + } +} + +.table-of-contents__list { + //@include breakpoint.up($_breakpoint) { + @include typography.style(small); + //} +} + +.table-of-contents__list .table-of-contents__list { + font-size: inherit; +} + +.table-of-contents--active { + //@include breakpoint.up($_breakpoint) { + // visibility: visible; + // opacity: 1; + //} +} diff --git a/partials/external/tocbot.hbs b/partials/external/tocbot.hbs new file mode 100644 index 0000000..0131916 --- /dev/null +++ b/partials/external/tocbot.hbs @@ -0,0 +1 @@ + diff --git a/post.hbs b/post.hbs index eca3bd6..370d81c 100644 --- a/post.hbs +++ b/post.hbs @@ -82,10 +82,16 @@ + {{^has tag="galerie"}} +
{{!-- TOC holder for `position: sticky` --}} + +
+ {{/has}} +
-