You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte/site/src/routes/guide/index.html

347 lines
7.4 KiB

<script context="module">
export async function preload() {
const sections = await this.fetch(`guide.json`).then(r => r.json());
return { sections };
}
</script>
<script>
import { onMount, afterUpdate } from 'svelte';
import GuideContents from './_GuideContents.html';
import Icon from '../../components/Icon.html';
export let sections;
let active_section;
let container;
let aside;
let show_contents = false;
onMount(() => {
const anchors = container.querySelectorAll('[id]');
let positions;
const onresize = () => {
const { top } = container.getBoundingClientRect();
positions = [].map.call(anchors, anchor => {
return anchor.getBoundingClientRect().top - top;
});
}
let last_id = window.location.hash.slice(1);
const onscroll = () => {
const top = -window.scrollY;
let i = anchors.length;
while (i--) {
if (positions[i] + top < 40) {
const anchor = anchors[i];
const { id } = anchor;
if (id !== last_id) {
active_section = id;
last_id = id;
}
return;
}
}
};
window.addEventListener('scroll', onscroll, true);
window.addEventListener('resize', onresize, true);
// wait for fonts to load...
const timeouts = [
setTimeout(onresize, 1000),
setTimeout(onresize, 5000)
];
onresize();
onscroll();
return () => {
window.removeEventListener('scroll', onscroll, true);
window.removeEventListener('resize', onresize, true);
timeouts.forEach(timeout => clearTimeout(timeout));
};
});
</script>
<style>
aside {
/* display: none; */
position: fixed;
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: 3.4rem;
height: 3.4rem;
}
aside.open {
width: calc(100vw - 1.6rem);
height: calc(100vh - var(--nav-h) - 7rem);
}
aside.open::before {
content: '';
position: absolute;
left: 0;
bottom: calc(100vh - var(--nav-h) - 10.8rem);
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: 1.9em;
width: 100%;
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 {
position: absolute;
font-family: var(--font);
overflow-y: auto;
width: calc(100vw - 4.8rem);
height: calc(100vh - var(--nav-h) - 10.8rem);
padding: 2em 0;
bottom: 2em;
}
.content {
width: 100%;
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: 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: 28rem;
}
}
@media (min-width: 1200px) { /* can't use vars in @media :( */
aside {
display: block;
left: calc(50vw - (60rem - var(--side-nav)));
}
.content {
width: 80rem;
padding-left: calc(50vw - 32rem);
box-sizing: content-box;
/* padding-right: calc(50% - 50rem); */
}
}
.content h2 {
margin-top: 16rem;
padding: 2rem 1.6rem 5.6rem 0.2rem;
border-top: 2px solid var(--second);
color: var(--second);
line-height: 1;
}
.content section:first-of-type > h2 {
margin-top: 0;
}
.content :global(.offset-anchor) {
position: relative;
display: block;
top: calc(-1 * (var(--nav-h) + var(--top-offset) - 1rem));
width: 0;
height: 0;
}
.content :global(.anchor) {
position: absolute;
display: block;
background: url(/icons/link.svg) 0 50% no-repeat;
background-size: 1em 1em;
width: 1.4em;
height: 1em;
left: -1.3em;
opacity: 0;
transition: opacity 0.2s;
border: none !important; /* TODO get rid of linkify */
}
@media (min-width: 768px) {
.content :global(h2):hover :global(.anchor),
.content :global(h3):hover :global(.anchor) {
opacity: 1;
}
}
.content :global(h3),
.content :global(h3 > code) {
font-weight: 700;
font-size: var(--h3);
color: var(--second);
margin: 6.4rem 0 1.6rem 0;
background: transparent;
line-height: 1;
}
.content :global(code) {
padding: .3rem .8rem .3rem;
margin: 0 0.2rem;
top: -.1rem;
background: #f4f4f4;
}
.content :global(pre) :global(code) {
padding: 0;
margin: 0;
top: 0;
background: transparent;
}
.content :global(.icon) {
width: 20px;
height: 20px;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
fill: none;
}
/* max line-length ~60 chars */
section > :global(p) {
max-width: var(--linemax)
}
small {
font-size: var(--h5);
float: right;
pointer-events: all;
color: var(--prime);
cursor: pointer;
}
/* no linkify on these */
small a { all: unset }
small a:before { all: unset }
section :global(blockquote) {
color: hsl(204, 100%, 50%);
border: 2px solid var(--flash);
padding-left: 8.8rem;
}
section :global(blockquote) :global(code) {
background: hsl(204, 100%, 95%) !important;
color: hsl(204, 100%, 50%);
}
section :global(blockquote::before) {
content: ' ';
position: absolute;
top: 1.5rem;
left: 3.2rem;
width: 3rem;
height: 3rem;
background-repeat: no-repeat;
background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='#40b3ff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z'/%3E%3Cline x1='12' y1='9' x2='12' y2='13'/%3E%3Cline x1='12' y1='17' x2='12' y2='17'/%3E%3C/svg%3E");
}
</style>
<svelte:head>
<title>Learn Svelte</title>
</svelte:head>
<div bind:this={container} class='content linkify listify'>
{#each sections as section}
<section data-id={section.slug}>
<h2>
<span class="offset-anchor" id={section.slug}></span>
<a href="#{section.slug}" class="anchor" aria-hidden></a>
{section.metadata.title}
<small>
<a href='https://github.com/sveltejs/svelte/edit/master/site/content/guide/{section.file}' title='edit this section'>
<Icon name='edit' /></a>
</small>
</h2>
{@html section.html}
</section>
{/each}
</div>
<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="{show_contents? 'close' : 'menu'}"/>
</button>
</aside>