diff --git a/assets/sprite.svg b/assets/sprite.svg index 2542006..ea133f1 100644 --- a/assets/sprite.svg +++ b/assets/sprite.svg @@ -1,5 +1,5 @@ - - + + @@ -14,12 +14,5 @@ - - - - - - - - - + + diff --git a/common/common.scss b/common/common.scss index 9d9c99c..55e8502 100644 --- a/common/common.scss +++ b/common/common.scss @@ -1,41 +1,26 @@ $padding-basis: 0.75em; -.d-toc-available { - // the toc increases the timeline container's width - // so as long as the toc is available in a topic - // we want this width to remain for the timeline - // so if the toc is toggled off, the position doesn't shift - - @media screen and (max-width: 1109px) { - .d-toc-wrapper { - width: 10em; - } - } - - @media screen and (min-width: 1110px) { - .container.posts { - grid-template-columns: auto 14.6em; - } - } -} - .d-toc-main { display: none; + width: 225px; + @media screen and (max-width: 1045px) { + .desktop-view & { + width: 150px; + } + } border-left: 1px solid var(--primary-low); box-sizing: border-box; a { display: block; padding: 0.15em 0; - color: var(--primary-700); + color: var(--primary-medium); &.scroll-to-bottom { - color: var(--tertiary); padding-left: $padding-basis; - margin-top: 0.5em; - font-size: var(--font-down-1); } } #d-toc { - max-height: calc(100dvh - 7em - var(--header-offset)); + max-height: calc(100vh - 4.5em - var(--header-offset)); + padding-bottom: 0.5em; overflow: auto; ul { list-style-type: none; @@ -62,7 +47,7 @@ $padding-basis: 0.75em; } } > a:hover { - color: var(--primary); + color: var(--primary-high); } &.direct-active > a { position: relative; @@ -139,61 +124,58 @@ a.d-toc-close { display: none; } -.d-toc-timeline-toggle { - display: none; - position: fixed; - bottom: 0; - @include ellipsis; - .d-icon-timeline { - margin-right: 0.25em; - } - - @media screen and (min-height: 1200px) { - // on tall screens we don't want this button - // to be incredibly distant - position: absolute; - .d-toc-timeline-visible & { - bottom: -4em; - } - bottom: -6.5em; - } -} - -.topic-navigation.with-timeline:has(.timeline-docked) { - // hide toggle when timeline is docked - // (firefox doesn't support :has yet) - .d-toc-timeline-toggle { - display: none; - } -} - -.d-toc-timeline-toggleable { - .d-toc-timeline-toggle { - display: block; - z-index: z("timeline"); - @media screen and (max-height: 480px) { - // avoid overlapping timeline - display: none; - } - } - .with-topic-progress { - .d-toc-main { - display: block; - } - .d-toc-timeline-toggle { - display: none; - } - } -} - .d-toc-timeline-visible { .d-toc-main, .d-toc-mini { display: block; } + // overlayed timeline (on mobile and narrow screens) + .topic-navigation.with-topic-progress { + .d-toc-wrapper { + position: fixed; + margin-top: 0.25em; + height: calc(100vh - 50px - var(--header-offset)); + opacity: 0.5; + right: -100vw; + top: var(--header-offset); + width: 75vw; + max-width: 350px; + background-color: var(--secondary); + box-shadow: var(--shadow-dropdown); + z-index: z("modal", "overlay"); + transition: all 0.2s ease-in-out; + .d-toc-main { + width: 100%; + padding: 0.5em; + height: 100%; + #d-toc { + max-height: calc(100% - 3em); + } + } + &.overlay { + right: 0; + width: 75vw; + opacity: 1; + .d-toc-main #d-toc li.d-toc-item ul { + transition: none; + } + } + + a.scroll-to-bottom, + a.d-toc-close { + display: inline-block; + padding: 0.5em; + } + + .d-toc-icons { + text-align: right; + } + } + } // core overrides when timeline is active - .timeline-container { + .timeline-container, + #topic-progress { display: none; } .container.posts .topic-navigation.with-topic-progress { @@ -201,88 +183,6 @@ a.d-toc-close { } } -// overlayed timeline (on mobile and narrow screens) -.topic-navigation.with-topic-progress { - .d-toc-timeline-toggle { - display: none; - } - .d-toc-wrapper { - position: fixed; - margin-top: 0.25em; - height: calc(100dvh - 50px - var(--header-offset)); - opacity: 0.5; - right: -100vw; - top: var(--header-offset); - width: 75vw; - max-width: 350px; - background-color: var(--secondary); - box-shadow: var(--shadow-dropdown); - z-index: z("modal", "overlay"); - transition: all 0.2s ease-in-out; - .d-toc-main { - width: 100%; - padding: 0.5em; - height: 100%; - #d-toc { - max-height: calc(100% - 2.25em); - } - } - &.overlay { - right: 0; - width: 75vw; - opacity: 1; - .d-toc-main { - display: block; - #d-toc li.d-toc-item ul { - transition: none; - } - } - } - - a.scroll-to-bottom { - margin-top: 0.33em; - } - - a.scroll-to-bottom, - a.d-toc-close { - display: inline-block; - padding: 0.5em; - } - - .d-toc-icons { - position: absolute; - background: var(--secondary); - right: 1.5em; - top: 0.25em; - z-index: z("timeline"); - } - } -} - -#topic-progress-wrapper { - align-items: stretch; - .d-toc-mini { - display: none; - - height: 100%; - .btn { - height: 100%; - } - } - - .staff & { - .topic-admin-menu-button-container { - margin-left: 0.5em; - } - } -} - -.d-toc-timeline-toggleable { - #topic-progress-wrapper .d-toc-mini { - display: block; - } -} - // core sets first child's top margin to 0 // ensure it's also 0 when TOC markup is first .cooked > div[data-theme-toc]:first-child + * { @@ -332,5 +232,11 @@ a.d-toc-close { .below-docs-topic-outlet.d-toc-wrapper { position: sticky; top: calc(var(--header-offset, 60px) + 1em); - max-height: calc(100dvh - 2em - var(--header-offset, 60px)); + max-height: calc(100vh - 2em - var(--header-offset, 60px)); + .mobile-view & { + display: none; + } + .d-toc-main { + display: block; + } } diff --git a/javascripts/discourse/connectors/after-topic-progress/d-toc-mini.hbs b/javascripts/discourse/connectors/after-topic-progress/d-toc-mini.hbs new file mode 100644 index 0000000..b26df5d --- /dev/null +++ b/javascripts/discourse/connectors/after-topic-progress/d-toc-mini.hbs @@ -0,0 +1,7 @@ +
+ +
\ No newline at end of file diff --git a/javascripts/discourse/connectors/before-topic-progress/d-toc-mini.js b/javascripts/discourse/connectors/after-topic-progress/d-toc-mini.js similarity index 72% rename from javascripts/discourse/connectors/before-topic-progress/d-toc-mini.js rename to javascripts/discourse/connectors/after-topic-progress/d-toc-mini.js index 3f89217..41476f0 100644 --- a/javascripts/discourse/connectors/before-topic-progress/d-toc-mini.js +++ b/javascripts/discourse/connectors/after-topic-progress/d-toc-mini.js @@ -6,9 +6,4 @@ export default class DTocMini extends Component { showTOCOverlay() { document.querySelector(".d-toc-wrapper").classList.toggle("overlay"); } - - @action - resetBodyClass() { - document.body.classList.add("d-toc-timeline-visible"); - } } diff --git a/javascripts/discourse/connectors/before-topic-progress/d-toc-mini.hbs b/javascripts/discourse/connectors/before-topic-progress/d-toc-mini.hbs deleted file mode 100644 index 93dddd4..0000000 --- a/javascripts/discourse/connectors/before-topic-progress/d-toc-mini.hbs +++ /dev/null @@ -1,3 +0,0 @@ -
- -
\ No newline at end of file diff --git a/javascripts/discourse/initializers/disco-toc-main.js b/javascripts/discourse/initializers/disco-toc-main.js index 2a7b598..f88561e 100644 --- a/javascripts/discourse/initializers/disco-toc-main.js +++ b/javascripts/discourse/initializers/disco-toc-main.js @@ -6,8 +6,6 @@ import { iconHTML } from "discourse-common/lib/icon-library"; import domUtils from "discourse-common/utils/dom-utils"; import I18n from "I18n"; -let TOChidden = localStorage.getItem("discourse_toc-hidden") === "true"; - export default { name: "disco-toc-main", @@ -82,31 +80,13 @@ export default { ); api.onAppEvent("topic:current-post-changed", (args) => { - const hasCookedTOC = document.querySelector(".d-toc-cooked"); - - // manages the timeline area width via CSS - if (hasCookedTOC) { - document.body.classList.add("d-toc-available"); + if (!document.querySelector(".d-toc-cooked")) { + return; } - - // manages timeline visibility - if (hasCookedTOC && args.post.post_number === 1) { - if (!TOChidden) { - handleButtonAndBody("show"); - } else { - handleButtonAndBody("hide"); - } - - // don't show the toggle if there's only 1 post - if (hasCookedTOC && args.post.topic.posts_count !== 1) { - document.body.classList.add("d-toc-timeline-toggleable"); - } + if (args.post.post_number === 1) { + document.body.classList.add("d-toc-timeline-visible"); } else { - handleButtonAndBody("hide"); - } - - if (args.post.topic.posts_count === 1) { - document.body.classList.remove("d-toc-timeline-toggleable"); + document.body.classList.remove("d-toc-timeline-visible"); } }); @@ -123,7 +103,7 @@ export default { }); api.cleanupStream(() => { - document.body.classList.remove("d-toc-available"); + document.body.classList.remove("d-toc-timeline-visible"); document.removeEventListener("click", this.clickTOC, false); }); }); @@ -170,65 +150,36 @@ export default { } }, - createMainDiv() { + insertTOC(headings) { const dToc = document.createElement("div"); dToc.classList.add("d-toc-main"); - dToc.innerHTML = `
${iconHTML( - "times" - )}
`; - return dToc; - }, - - createScrollLink() { - const scrollLink = document.createElement("a"); - scrollLink.href = "#"; - scrollLink.className = "scroll-to-bottom"; - scrollLink.title = I18n.t(themePrefix("post_bottom_tooltip")); - scrollLink.innerHTML = `${iconHTML("downward")} ${I18n.t( - themePrefix("jump_bottom") - )}`; - return scrollLink; - }, - - createToggleButton() { - const toggleButton = document.createElement("button"); - toggleButton.className = - "d-toc-timeline-toggle btn btn-default btn-icon-text"; - toggleButton.innerHTML = - iconHTML("timeline") + I18n.t(themePrefix("topic_timeline")); - - return toggleButton; - }, - - insertTOC(headings) { - const dToc = this.createMainDiv(); - const scrollLink = this.createScrollLink(); - this.toggleButton = this.createToggleButton(); + dToc.innerHTML = `
+ ${iconHTML("downward")} + ${iconHTML("times")}
`; const existing = document.querySelector(".d-toc-wrapper .d-toc-main"); - const wrapper = document.querySelector(".d-toc-wrapper"); - if (existing) { - wrapper.replaceChild(dToc, existing); + document.querySelector(".d-toc-wrapper").replaceChild(dToc, existing); } else { - wrapper.appendChild(dToc); - wrapper.appendChild(this.toggleButton); + document.querySelector(".d-toc-wrapper").appendChild(dToc); } const result = this.buildTOC(Array.from(headings)); - dToc.appendChild(result); - dToc.appendChild(scrollLink); + document.querySelector(".d-toc-main").appendChild(result); document.addEventListener("click", this.clickTOC, false); }, clickTOC(e) { const classNames = ["d-toc-timeline-visible", "archetype-docs-topic"]; - // toggle timeline visibility - if (e.target.closest(".d-toc-timeline-toggle")) { - handleButtonAndBody("toggle"); - e.preventDefault(); - return false; + if ( + !classNames.some((className) => + document.body.classList.contains(className) + ) + ) { + return; } // link to each heading @@ -261,7 +212,7 @@ export default { top: rect.bottom + window.scrollY - headerOffset() - 10, behavior: "smooth", }); - document.querySelector(".d-toc-wrapper").classList.remove("overlay"); + e.preventDefault(); return false; } @@ -283,14 +234,6 @@ export default { if (!e.target.closest(".d-toc-wrapper.overlay")) { document.querySelector(".d-toc-wrapper").classList.remove("overlay"); } - - if ( - !classNames.some((className) => - document.body.classList.contains(className) - ) - ) { - return; - } }, buildTOC(headings) { @@ -374,42 +317,3 @@ function parentsUntil(el, selector, filter) { } return result; } - -function handleButtonAndBody(action) { - const body = document.body; - const button = document.querySelector("button.d-toc-timeline-toggle"); - - switch (action) { - case "toggle": - body.classList.toggle("d-toc-timeline-visible"); - TOChidden = !TOChidden; - localStorage.setItem("discourse_toc-hidden", TOChidden.toString()); - - break; - - case "hide": - body.classList.remove( - "d-toc-timeline-visible", - "d-toc-timeline-toggleable" - ); - break; - - case "show": - body.classList.add("d-toc-timeline-visible", "d-toc-timeline-toggleable"); - break; - } - - if (button) { - const translationKey = body.classList.contains("d-toc-timeline-visible") - ? "topic_timeline" - : "table_of_contents"; - - const icon = body.classList.contains("d-toc-timeline-visible") - ? "timeline" - : "stream"; - - button.innerHTML = `${iconHTML(icon)}${I18n.t( - themePrefix(translationKey) - )} `; - } -} diff --git a/locales/en.yml b/locales/en.yml index 594af2a..7b587ec 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -1,7 +1,5 @@ en: - table_of_contents: Table of contents - topic_timeline: Topic timeline - jump_bottom: Jump to replies + table_of_contents: table of contents insert_table_of_contents: Insert table of contents post_bottom_tooltip: Navigate to post controls theme_metadata: diff --git a/test/acceptance/toc-test.js b/test/acceptance/toc-test.js index 237fafb..bf34a6b 100644 --- a/test/acceptance/toc-test.js +++ b/test/acceptance/toc-test.js @@ -1,4 +1,4 @@ -import { click, visit } from "@ember/test-helpers"; +import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import topicFixtures from "discourse/tests/fixtures/topic"; import { @@ -66,14 +66,6 @@ acceptance("DiscoTOC - main", function (needs) { "heading gets an ID even when it has no Latin characters" ); }); - - test("TOC can be toggled to reveal timeline", async function (assert) { - await visit("/t/internationalization-localization/280"); - assert.ok(exists(".d-toc-timeline-toggle"), "TOC toggle exists"); - - await click(".d-toc-timeline-toggle"); - assert.ok(exists(".topic-timeline"), "The timeline is shown on toggle"); - }); }); acceptance("DiscoTOC - off", function (needs) {