diff --git a/src/components/app-footer/style.css b/src/components/app-footer/style.css index 7f91964b..9fdf21ec 100644 --- a/src/components/app-footer/style.css +++ b/src/components/app-footer/style.css @@ -2,7 +2,7 @@ width:100%; color:#585a5c; display: flex; - flex-direction: row; + flex-wrap: wrap; align-items: center; justify-content: center; position: relative; diff --git a/src/components/app-layout/components/layout-header/component-browser.js b/src/components/app-layout/components/layout-header/component-browser.js index 9e3190c5..279437e0 100644 --- a/src/components/app-layout/components/layout-header/component-browser.js +++ b/src/components/app-layout/components/layout-header/component-browser.js @@ -33,7 +33,7 @@ module.exports = { }); handleScroll(); - window.addEventListener("scroll", handleScroll); + window.addEventListener("scroll", handleScroll, { passive: true }); }, reset() { this.removeClass(classNames.fixed); diff --git a/src/components/app-layout/components/layout-header/index.marko b/src/components/app-layout/components/layout-header/index.marko index f3b48b7c..15293170 100644 --- a/src/components/app-layout/components/layout-header/index.marko +++ b/src/components/app-layout/components/layout-header/index.marko @@ -1,16 +1,17 @@ - - - - - - - Docs - Try Online - GitHub - - - ☰ - - + + + + + Docs + Try Online + GitHub + + + + + + Menu + + diff --git a/src/components/app-layout/components/layout-header/style.css b/src/components/app-layout/components/layout-header/style.css index 96ed46e8..7d74bffc 100644 --- a/src/components/app-layout/components/layout-header/style.css +++ b/src/components/app-layout/components/layout-header/style.css @@ -1,112 +1,87 @@ .site-header { - position:absolute; - top:0; - left:0; - right:0; - background-color:#fff; - height:4em; - width:100%; - border-bottom:1px solid #fff; - transition:all 0.3s; + position: sticky; + top: 0; + left: 0; z-index: 99; - transform:translate3d(0, 1px, 0); + min-height: 4em; + width: 100%; + display: flex; + flex-wrap: wrap; + align-content: space-between; + align-items: center; + justify-content: center; + background: #fff; + transform: translate3d(0, 1px, 0); + transition: transform 0.3s; } - .site-header.headspace--fixed { - position:fixed; - transform:translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } .site-header.headspace--hidden { - transform:translate3d(0, -4em, 0); /* y value should be -1 * height */ -} -.site-header .content { - display: flex; - flex-direction:row; - justify-content:space-between; - align-items:center; - flex:1; -} - -.site-header.headspace--fixed, -body:not(.home) .site-header { - border-bottom-color:#dbdddf; - box-shadow: 0 0 0.7em rgba(0,5,10,0.15); -} - -body { - padding-top:4em; -} - -.site-banner { - height:1.5em; - color:#fff; - background:#09d; - text-align:center; + transform: translate3d(0, -4em, 0); /* y value should be -1 * height */ } -.site-banner a { - color:#fff; - text-decoration: underline; +/* using a pseudo-element instead of `box-shadow` because of https://ishadeed.com/article/new-facebook-css/#using-an-image-for-the-shadow */ +.site-header.headspace--fixed::after, +body:not(.home) .site-header::after { + content: ""; + position: absolute; + top: 100%; + left: 0; right: 0; + border-top: #dbdddf 1px solid; + height: 0.7em; + background: linear-gradient(rgba(0, 5, 10, 5%), rgba(0, 5, 10, 0%)); + pointer-events: none; } .site-logo { - height:2.2em; - margin-left:2em; - display:block; + height: 2.2em; + margin-left: 2em; + display: block; /* remove descender space underneath */ } -.site-header button.menu { - display:none; - border:0; - background:transparent; - font-size:2em; - padding:0.5em; - padding-right:1em; - cursor:pointer; - line-height:1em; +.site-menu-button { + border: 1px solid transparent; /* for High-Contrast Mode */ + background: none; + font-size: 1em; + line-height: 1; + padding: 0.5em; + margin: 0 0.5em; + border-radius: 99rem; + color: #595959; +} +.site-menu-button:hover { + background: radial-gradient(circle closest-side, #ccc 98%, rgba(0,0,0,0) 99%); +} +@media (min-width: 45em) { + .site-menu-button { + display: none; + } } -.site-header .stuff { - display: flex; - flex-direction: row; - justify-content: flex-end; - flex:1; -} -@media (max-width:45em) { - .site-header button.menu { - display:block; - } +.site-menu-icon { + display: block; + font-size: 2em; + margin: auto; } .site-menu { display: flex; - flex-direction:row; align-items: center; + justify-content: flex-end; + flex-grow: 1; } .site-menu > a { - display:flex; - justify-content:center; - align-items:center; - height:4em; - padding:1.5em; + padding: 1em 1.5em; text-decoration: none; - color:#595959; + color: #595959; } -.site-menu > a:hover { +.site-menu > a:is(:hover, :focus) { text-decoration: underline; } -@media (max-width:45em) { - .site-menu > .search { - display:none; - } - .site-menu { - align-items: stretch; - flex:1; - max-width: 20em; - } - .site-menu > a { - padding:0; - flex:1; +@media (max-width: 45em) { + .site-search { + display: none; } } diff --git a/src/components/app-layout/components/layout-sidebar/component-browser.js b/src/components/app-layout/components/layout-sidebar/component-browser.js index 05a91f4c..4d6d4dc7 100644 --- a/src/components/app-layout/components/layout-sidebar/component-browser.js +++ b/src/components/app-layout/components/layout-sidebar/component-browser.js @@ -1,79 +1,73 @@ var siteHeaderEvents = require("../layout-header/events"); -var forEach = [].forEach; -var filter = [].filter; -var slice = [].slice; +var { filter } = []; var siteHeaderComponent; module.exports = { onMount() { - this.preventOverscroll(); this.listenForHeaderChanges(); this.initScrollSpy(); }, initScrollSpy() { - var headersSelector = [1, 2, 3, 4, 5, 6] - .map(n => ".doc-content h" + n) - .join(","); - var headers = slice.call(document.querySelectorAll(headersSelector)); + var headers = [...document.querySelectorAll(".doc-content .heading")]; var waiting = false; + if (!headers.length) { return; } + + this.subscribeTo(window).on("scroll", () => { + if (waiting) { return; } + + waiting = true; + setTimeout(() => { + var threshold = window.innerHeight / 3; + var closestHeader; + var closestTop; + + headers.map(header => { + var { top } = header.getBoundingClientRect(); + if ( + closestTop == null || + (top < threshold && Math.abs(top) < Math.abs(closestTop)) + ) { + closestTop = top; + closestHeader = header; + } + }); + + var anchor = closestHeader.id; + var anchorEl = + this.el.querySelector('a[href="#' + anchor + '"]') || + this.el.querySelector("a.selected"); + var targetAnchor = anchorEl; + var childList = targetAnchor.nextSibling; + + if (childList) { + childList.querySelectorAll("a[href^='#']").forEach(a => + a.classList.remove("selected") + ); + } - headers.length && - this.subscribeTo(window).on("scroll", () => { - if (!waiting) { - waiting = true; - setTimeout(() => { - var threshold = window.innerHeight / 3; - var closestHeader; - var closestTop; - - headers.map(header => { - var top = header.getBoundingClientRect().top; - if ( - closestTop == null || - (top < threshold && Math.abs(top) < Math.abs(closestTop)) - ) { - closestTop = top; - closestHeader = header; - } - }); - - var anchor = closestHeader.id; - var anchorEl = - this.el.querySelector('a[href="#' + anchor + '"]') || - this.el.querySelector("a.selected"); - var targetAnchor = anchorEl; - var childList = targetAnchor.nextSibling; - - if (childList) { - forEach.call(childList.querySelectorAll("a[href^=\\#]"), a => - a.classList.remove("selected") - ); - } - - while (targetAnchor) { - var parentList = targetAnchor.closest("ul"); - var siblings = - parentList && - filter.call( - parentList.querySelectorAll(":scope > li > a[href^=\\#]"), - a => a !== targetAnchor - ); - siblings && siblings.forEach(a => a.classList.remove("selected")); - targetAnchor.classList.add("selected"); - targetAnchor = parentList && parentList.previousElementSibling; - } - - this.scrollAnchorIntoView(anchorEl); - - waiting = false; - }, 50); + while (targetAnchor) { + var parentList = targetAnchor.closest("ol"); + var siblings = + parentList && + filter.call( + parentList.querySelectorAll(":scope > li > a[href^='#']"), + a => a !== targetAnchor + ); + siblings && siblings.forEach(a => a.classList.remove("selected")); + targetAnchor.classList.add("selected"); + targetAnchor = parentList && parentList.previousElementSibling; } - }); + + this.scrollAnchorIntoView(anchorEl); + + waiting = false; + }, 50); + }); }, listenForHeaderChanges() { - forEach.call(this.el.querySelectorAll("a[href^=\\#]"), a => { + this.el.querySelectorAll("a[href^='#']").forEach(a => { this.subscribeTo(a).on("click", () => { siteHeaderComponent.hide(); siteHeaderComponent.pause(); @@ -83,7 +77,7 @@ module.exports = { }); // handles nested selected links - var selectedLink = slice.call(this.el.querySelectorAll("a.selected")).pop(); + var selectedLink = [...this.el.querySelectorAll("a.selected")].pop(); selectedLink && this.subscribeTo(selectedLink).on("click", e => { @@ -94,8 +88,7 @@ module.exports = { this.subscribeTo(siteHeaderEvents) .on("reset", () => { - this.el.classList.remove("no-header"); - this.el.classList.remove("fixed"); + this.el.classList.remove("no-header", "fixed"); setTimeout(() => this.el.classList.remove("transition"), 0); }) .on("fix", () => { @@ -104,54 +97,21 @@ module.exports = { setTimeout(() => this.el.classList.add("transition"), 0); }) .on("hide", () => { - this.el.classList.add("no-header"); - this.el.classList.add("fixed"); + this.el.classList.add("no-header", "fixed"); setTimeout(() => this.el.classList.add("transition"), 0); }) .on("toggle-menu", () => { - if (this.el.classList.contains("show")) { - this.el.classList.remove("show"); - document.body.style.overflow = ""; - } else { - this.el.classList.add("show"); - } + this.el.classList.toggle("show"); }) - .on("create", _siteHeaderComponent => { - siteHeaderComponent = _siteHeaderComponent; - + .on("create", siteHeaderComponent => { if (window.pageYOffset > siteHeaderComponent.el.offsetHeight) { - this.el.classList.add("no-header"); - this.el.classList.add("fixed"); + this.el.classList.add("no-header", "fixed"); } }); }, - preventOverscroll() { - var sidebar = this.getEl("sidebar"); - this.subscribeTo(document.body).on("wheel", e => { - var delta = e.deltaY; - var scrollTarget = sidebar.scrollTop + delta; - var topY = 0; - var bottomY = sidebar.scrollHeight - sidebar.offsetHeight; - var atTop = scrollTarget <= topY; - var atBottom = scrollTarget >= bottomY; - - if ((delta < 0 && atTop) || (delta > 0 && atBottom)) { - if (e.target === sidebar || sidebar.contains(e.target)) { - if (atTop && sidebar.scrollTop != topY) { - sidebar.scrollTop = topY; - } else if (atBottom && sidebar.scrollTop != bottomY) { - sidebar.scrollTop = bottomY; - } - e.preventDefault(); - } - } - }); - }, - scrollAnchorIntoView(anchorEl) { var sidebar = this.getEl("sidebar"); - var anchorTop = anchorEl.offsetTop; var sidebarScrollTop = sidebar.scrollTop; var sidebarHeight = sidebar.offsetHeight; var sidebarScrollBottom = sidebarScrollTop + sidebarHeight; @@ -160,7 +120,7 @@ module.exports = { var parentList; while (true) { - parentList = targetList.parentNode.closest("ul"); + parentList = targetList.parentNode.closest("ol"); if (parentList && parentList.offsetHeight < sidebarHeight) { targetList = parentList; } else { @@ -181,6 +141,5 @@ module.exports = { hide() { this.el.classList.remove("show"); - document.body.style.overflow = ""; } }; diff --git a/src/components/app-layout/components/layout-sidebar/components/version-switcher/index.marko b/src/components/app-layout/components/layout-sidebar/components/version-switcher/index.marko index 2d8ca1cc..889ca0d2 100644 --- a/src/components/app-layout/components/layout-sidebar/components/version-switcher/index.marko +++ b/src/components/app-layout/components/layout-sidebar/components/version-switcher/index.marko @@ -1,8 +1,21 @@ import { version } from "marko/package.json"; - +version${' '} + + + +style { + .version-select { + display: inline-block; + font-size: 0.8rem; + color: #666; + } + .version-select > select { + vertical-align: bottom; + } +} diff --git a/src/components/app-layout/components/layout-sidebar/index.marko b/src/components/app-layout/components/layout-sidebar/index.marko index 24388243..2387a1a9 100644 --- a/src/components/app-layout/components/layout-sidebar/index.marko +++ b/src/components/app-layout/components/layout-sidebar/index.marko @@ -5,50 +5,36 @@ import createOverviewTree from '../../../../utils/create-overview-tree'; static const parentTree = createOverviewTree(structure); static function getDocData(currentDoc, section, doc) { - let docSlug; - let selected; + let slug, selected, title; - let docTitle = doc; if (typeof doc === 'object') { - docTitle = doc.title; - - let sectionTitleSlug = formatSlug(section.title); - let titleSlug = formatSlug(docTitle); - - docSlug = `${sectionTitleSlug}-${titleSlug}-overview`; - + title = doc.title; + slug = formatSlug(`${section.title}-${title}-overview`); // Select the parents of "selected" documents, if they exist - selected = (parentTree[currentDoc] && parentTree[currentDoc][docSlug]) || (docSlug === currentDoc); + selected = parentTree[currentDoc]?.[slug] || (slug === currentDoc); } else { - docSlug = formatSlug(docTitle); - selected = docSlug === currentDoc; + title = doc; + slug = formatSlug(title); + selected = slug === currentDoc; } - docSlug += '/'; - - return { - docTitle, - docSlug, - selected - }; + return { title, slug, selected }; } -
    +
      - $ let title = section.title.toUpperCase(); - $ let overviewSlug = formatSlug(title); - ${title} + ${section.title} + $ let { title, slug, selected } = getDocData(input.currentDoc, section, doc);
    1. - $ let { docTitle, docSlug, selected } = getDocData(input.currentDoc, section, doc); - - ${docTitle} + + ${title} @@ -61,13 +47,15 @@ static function getDocData(currentDoc, section, doc) {
    2. -
+ - - ✕ -

Marko

- +