mobile contents menu

pull/1921/head
Rich Harris 6 years ago
parent d9c1697310
commit 3771c12392

@ -4,6 +4,7 @@
export let sections = [];
export let active_section = null;
export let show_contents;
onMount(() => {
// ------------------------------------------
@ -40,6 +41,10 @@
let ul;
afterUpdate(() => {
// bit of a hack — prevent sidebar scrolling if
// TOC is open on mobile
if (show_contents && window.innerWidth < 832) return;
const active = ul.querySelector('.active');
if (active) {
@ -65,36 +70,7 @@
});
</script>
<ul bind:this={ul} class="guide-toc">
{#each sections as section}
<li>
<a class="section" class:active="{section.slug === active_section}" href="guide#{section.slug}">
{section.metadata.title}
{#if section.slug === active_section}
<Icon name="arrow-right" />
{/if}
</a>
{#each section.subsections as subsection}
<!-- see <script> below: on:click='scrollTo(event, subsection.slug)' -->
<a class="subsection" class:active="{subsection.slug === active_section}" href="guide#{subsection.slug}">
{subsection.title}
{#if subsection.slug === active_section}
<Icon name="arrow-right" />
{/if}
</a>
{/each}
</li>
{/each}
</ul>
<style>
.guide-toc {
--section-clr: white;
}
.guide-toc li {
display: block;
line-height: 1.2;
@ -105,7 +81,6 @@
display: block;
padding: 0 0 .8rem 0;
font: 400 var(--h6) var(--font);
color: var(--section-clr);
text-transform: uppercase;
letter-spacing: 0.12em;
}
@ -120,10 +95,29 @@
.section:hover,
.subsection:hover { color: var(--flash) }
.active { color: var(--prime) }
</style>
@media screen and (min-width: 768px) {
.guide-toc {
--section-clr: black;
}
}
</style>
<ul bind:this={ul} class="guide-toc">
{#each sections as section}
<li>
<a class="section" class:active="{section.slug === active_section}" href="guide#{section.slug}">
{section.metadata.title}
{#if section.slug === active_section}
<Icon name="arrow-right" />
{/if}
</a>
{#each section.subsections as subsection}
<!-- see <script> below: on:click='scrollTo(event, subsection.slug)' -->
<a class="subsection" class:active="{subsection.slug === active_section}" href="guide#{subsection.slug}">
{subsection.title}
{#if subsection.slug === active_section}
<Icon name="arrow-right" />
{/if}
</a>
{/each}
</li>
{/each}
</ul>

@ -10,15 +10,12 @@
import GuideContents from './_GuideContents.html';
import Icon from '../../components/Icon.html';
// NOT YET
// get offset from css-vars (for smooth-scroll)
// import CustomProperties from '../../utils/css-custom-properties.js'
export let sections;
let active_section;
let container;
let aside;
let show_contents = false;
onMount(() => {
const anchors = container.querySelectorAll('[id]');
@ -75,65 +72,130 @@
<style>
aside {
display: none;
/* display: none; */
position: fixed;
left: 0;
top: var(--nav-h);
width: var(--sidebar-w);
height: calc(100vh - var(--nav-h));
background-color: white;
left: 0.8rem;
bottom: 0.8rem;
width: 2em;
height: 2em;
overflow: hidden;
border: 1px solid #eee;
box-shadow: 1px 1px 6px rgba(0,0,0,0.1);
border-radius: var(--border-r);
padding: 1.6rem;
transition: width 0.2s, height 0.2s;
}
aside button {
position: absolute;
bottom: 0;
left: 0;
width: 2em;
height: 2em;
}
aside.open {
width: calc(100vw - 1.6rem);
height: calc(100vh - var(--nav-h) - 1.8rem);
}
aside.open::before {
content: '';
position: absolute;
left: 0;
bottom: calc(100vh - var(--nav-h) - 5.6rem);
width: 100%;
height: 2em;
background: linear-gradient(to top, rgba(255,255,255,0) 0%, rgba(255,255,255,0.7) 50%, rgba(255,255,255,1) 100%);
pointer-events: none;
z-index: 2;
}
aside::after {
content: '';
position: absolute;
left: 0;
bottom: 0;
bottom: 2em;
width: 100%;
height: var(--top-offset);
height: 2em;
background: linear-gradient(to bottom, rgba(255,255,255,0) 0%, rgba(255,255,255,0.7) 50%, rgba(255,255,255,1) 100%);
pointer-events: none;
}
.sidebar {
padding: var(--top-offset) 3.2rem var(--top-offset) 0;
position: absolute;
font-family: var(--font);
overflow-y: auto;
height: 100%;
width: calc(var(--sidebar-w) + 5rem);
width: calc(100vw - 4.8rem);
height: calc(100vh - var(--nav-h) - 5.6rem);
padding: 2em 0;
bottom: 2em;
}
.content {
width: 100%;
max-width: calc(var(--main-width) + 2 * var(--side-nav));
max-width: calc(var(--main-width) + var(--side-nav));
margin: 0 auto;
-moz-tab-size: 2;
padding: var(--top-offset) 0;
tab-size: 2;
}
@media (min-width: 52em) { /* can't use vars in @media :( */
@media (min-width: 832px) { /* can't use vars in @media :( */
aside {
display: block;
width: var(--sidebar-w);
height: calc(100vh - var(--nav-h));
top: var(--nav-h);
left: var(--side-nav);
overflow: hidden;
box-shadow: none;
border: none;
overflow: hidden;
padding: 0;
}
aside.open::before {
display: none;
}
aside::after {
content: '';
bottom: 0;
height: var(--top-offset);
}
aside button {
display: none;
}
.sidebar {
padding: var(--top-offset) 3.2rem var(--top-offset) 0;
font-family: var(--font);
overflow-y: auto;
height: 100%;
bottom: auto;
width: calc(var(--sidebar-w) + 5rem);
}
.content {
max-width: none;
padding-left: 32rem;
padding-left: 28rem;
}
}
@media (min-width: 89.6rem) { /* can't use vars in @media :( */
@media (min-width: 1200px) { /* can't use vars in @media :( */
aside {
display: block;
left: calc(50% - 60rem);
left: calc(50vw - (60rem - var(--side-nav)));
}
.content {
max-width: none;
padding-left: calc(50% - 30rem);
padding-right: calc(50% - 50rem);
width: 80rem;
padding-left: calc(50vw - 32rem);
box-sizing: content-box;
/* padding-right: calc(50% - 50rem); */
}
}
@ -274,8 +336,12 @@
{/each}
</div>
<aside bind:this={aside} class="sidebar-container">
<div class="sidebar">
<GuideContents {sections} {active_section} />
<aside bind:this={aside} class="sidebar-container" class:open={show_contents}>
<div class="sidebar" on:click="{() => show_contents = false}"> <!-- scroll container -->
<GuideContents {sections} {active_section} {show_contents} />
</div>
<button on:click="{() => show_contents = !show_contents}">
<Icon name="menu"/>
</button>
</aside>
Loading…
Cancel
Save