various guide improvements

pull/1913/head
Rich Harris 6 years ago
parent 3c06379398
commit 7aa612f61d

@ -3,14 +3,12 @@ title: Transitions
---
### Transitions
Transitions allow elements to enter and leave the DOM gracefully, rather than suddenly appearing and disappearing.
```html
<!-- { title: 'Transitions' } -->
<script>
import { fade } from 'svelte/transition.js';
import { fade } from 'svelte/transition';
let visible = false;
</script>
@ -21,12 +19,12 @@ Transitions allow elements to enter and leave the DOM gracefully, rather than su
{/if}
```
Transitions can have parameters — typically `delay` and `duration`, but often others, depending on the transition in question. For example, here's the `fly` transition from the [svelte-transitions](https://github.com/sveltejs/svelte-transitions) package:
Transitions can have parameters — typically `delay` and `duration`, but often others, depending on the transition in question. For example, here's the `fly` transition:
```html
<!-- { title: 'Transition with parameters' } -->
<script>
import { fly } from 'svelte-transitions';
import { fly } from 'svelte/transition';
let visible = false;
</script>
@ -37,6 +35,9 @@ Transitions can have parameters — typically `delay` and `duration`, but often
{/if}
```
### In and out
An element can have separate `in` and `out` transitions:
```html
@ -53,7 +54,27 @@ An element can have separate `in` and `out` transitions:
{/if}
```
Transitions are simple functions that take a `node` and any provided `parameters` and return an object with the following properties:
### Built-in transitions
Svelte comes with a handful of ready-to-use transitions:
```html
<!-- { repl: false } -->
<script>
import {
fade,
fly,
slide,
draw
} from 'svelte/transition';
</script>
```
### Custom transitions
You can also make your own. Transitions are simple functions that take a `node` and any provided `parameters` and return an object with the following properties:
* `duration` — how long the transition takes in milliseconds
* `delay` — milliseconds before the transition starts

@ -104,37 +104,8 @@
</symbol>
<symbol id="link" class="icon" viewBox="0 0 24 24">
<!-- <path d="
M10.5,13.5
C8.5,11.5 9.5,11.5 9.5,10.5
C8,9 13,3.5, 16,3
C19,3 21,6 21,8
C21,9,20,9,19,11"/>
<path d="
M13.5,10.5
C15.5,13.5 14.5,13.5 14.5,13.5
C16,15 11,21.5, 8,21
C5,21 3,18 3,16
C3,15,4,15,5,13"/> -->
<path d="
M9,7
L6,7
A2 2 0 0 0 6,17
L9,17
"/>
<path d="
M15,7
L18,7
A2 2 0 0 1 18,17
L15,17
"/>
<path d="
M7,12
L17,12
"/>
<path d="M9,7L6,7A2 2 0 0 0 6,17L9,17"/>
<path d="M15,7L18,7A2 2 0 0 1 18,17L15,17"/>
<path d="M7,12L17,12"/>
</symbol>
</svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

@ -1,5 +1,5 @@
<script>
import { onMount } from 'svelte';
import { onMount, afterUpdate } from 'svelte';
import Icon from '../../components/Icon.html';
export let sections = [];
@ -36,21 +36,54 @@
window.removeEventListener('hashchange', onhashchange, false);
};
});
let ul;
afterUpdate(() => {
const active = ul.querySelector('.active');
if (active) {
const { top, bottom } = active.getBoundingClientRect();
const min = 200;
const max = window.innerHeight - 200;
if (top > max) {
ul.parentNode.scrollBy({
top: top - max,
left: 0,
behavior: 'smooth'
});
} else if (bottom < min) {
ul.parentNode.scrollBy({
top: bottom - min,
left: 0,
behavior: 'smooth'
});
}
}
});
</script>
<ul class='guide-toc'>
<ul bind:this={ul} class="guide-toc">
{#each sections as section}
<li>
<a class='section {section.slug === active_section ? "active": ""}' href='guide#{section.slug}'>
{section.metadata.title} {#if section.slug === active_section}
<Icon name='arrow-right' /> {/if}
<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 {subsection.slug === active_section ? "active": ""}' href='guide#{subsection.slug}'>
{subsection.title} {#if subsection.slug === active_section}
<Icon name='arrow-right' /> {/if}
<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>

@ -4,7 +4,7 @@ import * as fleece from 'golden-fleece';
import process_markdown from '../../utils/_process_markdown.js';
import marked from 'marked';
import prismjs from 'prismjs'; // prism-highlighter smaller footprint [hljs: 192.5k]
import Prism from 'prismjs'; // prism-highlighter smaller footprint [hljs: 192.5k]
require('prismjs/components/prism-bash');
const langs = {
@ -34,16 +34,25 @@ const escaped = {
const unescaped = Object.keys(escaped).reduce(
(unescaped, key) => ((unescaped[escaped[key]] = key), unescaped),
{},
{}
);
function unescape(str) {
return String(str).replace(/&.+?;/g, match => unescaped[match] || match);
}
const blockTypes = 'blockquote html heading hr list listitem paragraph table tablerow tablecell'.split(
' ',
);
const blockTypes = [
'blockquote',
'html',
'heading',
'hr',
'list',
'listitem',
'paragraph',
'table',
'tablerow',
'tablecell'
];
function extractMeta(line, lang) {
try {
@ -83,6 +92,7 @@ export default function() {
const { content, metadata } = process_markdown(markdown);
const subsections = [];
const groups = [];
let group = null;
let uid = 1;
@ -91,7 +101,7 @@ export default function() {
renderer.code = (source, lang) => {
source = source.replace(/^ +/gm, match =>
match.split(' ').join('\t'),
match.split(' ').join('\t')
);
const lines = source.split('\n');
@ -140,12 +150,50 @@ export default function() {
const highlighted = Prism.highlight(
source,
Prism.languages[plang],
lang,
lang
);
return `<div class='${className}'>${prefix}<pre class='language-${plang}'><code>${highlighted}</code></pre></div>`;
};
const seen = new Set();
renderer.heading = (text, level, rawtext) => {
if (level <= 3) {
const slug = rawtext
.toLowerCase()
.replace(/[^a-zA-Z0-9]+/g, '-')
.replace(/^-/, '')
.replace(/-$/, '');
if (seen.has(slug)) throw new Error(`Duplicate slug ${slug}`);
seen.add(slug);
if (level === 3) {
const title = unescape(
text
.replace(/<\/?code>/g, '')
.replace(/\.(\w+)(\((.+)?\))?/, (m, $1, $2, $3) => {
if ($3) return `.${$1}(...)`;
if ($2) return `.${$1}()`;
return `.${$1}`;
})
);
subsections.push({ slug, title });
}
return `
<h${level}>
<span id="${slug}" class="offset-anchor"></span>
<a href="guide#${slug}" class="anchor" aria-hidden="true"></a>
${text}
</h${level}>`;
}
return `<h${level}>${text}</h${level}>`;
};
blockTypes.forEach(type => {
const fn = renderer[type];
renderer[type] = function() {
@ -185,29 +233,10 @@ export default function() {
};
}),
json5: json5 && json5.source,
}),
})
);
});
const subsections = [];
const pattern = /<h3 id="(.+?)">(.+?)<\/h3>/g;
let match;
while ((match = pattern.exec(html))) {
const slug = match[1];
const title = unescape(
match[2]
.replace(/<\/?code>/g, '')
.replace(/\.(\w+)(\((.+)?\))?/, (m, $1, $2, $3) => {
if ($3) return `.${$1}(...)`;
if ($2) return `.${$1}()`;
return `.${$1}`;
}),
);
subsections.push({ slug, title });
}
return {
html: html.replace(/@@(\d+)/g, (m, id) => hashes[id] || m),
metadata,

@ -6,7 +6,7 @@
</script>
<script>
import { onMount } from 'svelte';
import { onMount, afterUpdate } from 'svelte';
import GuideContents from './_GuideContents.html';
import Icon from '../../components/Icon.html';
@ -18,6 +18,7 @@
let active_section;
let container;
let aside;
onMount(() => {
const anchors = container.querySelectorAll('[id]');
@ -148,21 +149,54 @@
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 */
}
.content :global(h2):hover :global(.anchor),
.content :global(h3):hover :global(.anchor) {
opacity: 1;
}
.content :global(h3),
.content :global(h3 > code) {
pointer-events: none;
font-weight: 700;
font-size: var(--h3);
color: var(--second);
padding: 6.4rem 0 1.6rem 0;
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: #f9f9f9;
background: #f4f4f4;
}
.content :global(pre) :global(code) {
padding: 0;
margin: 0;
top: 0;
background: transparent;
}
.content :global(.icon) {
@ -194,11 +228,16 @@
section :global(blockquote) {
color: var(--flash);
border: 2px solid currentColor;
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;
@ -217,8 +256,11 @@
<div bind:this={container} class='content linkify listify'>
{#each sections as section}
<section id='{section.slug}'>
<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'>
@ -230,8 +272,8 @@
{/each}
</div>
<aside class="sidebar-container">
<aside bind:this={aside} class="sidebar-container">
<div class="sidebar">
<GuideContents {sections} />
<GuideContents {sections} {active_section} />
</div>
</aside>

@ -219,6 +219,7 @@ body {
h1, h2, h3, h4, h5, h6, blockquote {
margin: 0;
color: var(--heading);
position: relative;
}
h1, h2, h3, h4, h5, h6 { font-weight: 700 }
@ -257,6 +258,7 @@ code {
pre code {
top: 0;
white-space: inherit;
background-color: none;
}
::selection {
@ -268,7 +270,6 @@ pre code {
h1, h2 {
font-family: var(--font);
line-height: 1.2;
pointer-events: none;
}
li:not(.white) > h2 {
@ -407,6 +408,7 @@ a:hover > .icon { stroke: var(--flash) }
width: .8rem;
height: 0.8rem;
border-radius: 2px;
opacity: 0.7;
}
.listify ol { list-style: decimal }

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" viewBox="0 0 24 24">
<path fill="#aa1e1e" d="M16,6H13V7.9H16C18.26,7.9 20.1,9.73 20.1,12A4.1,4.1 0 0,1 16,16.1H13V18H16A6,6 0 0,0 22,12C22,8.68 19.31,6 16,6M3.9,12C3.9,9.73 5.74,7.9 8,7.9H11V6H8A6,6 0 0,0 2,12A6,6 0 0,0 8,18H11V16.1H8C5.74,16.1 3.9,14.26 3.9,12M8,13H16V11H8V13Z" />
<g fill="none" stroke="#333">
<path d="M9,7L6,7A2 2 0 0 0 6,17L9,17"/>
<path d="M15,7L18,7A2 2 0 0 1 18,17L15,17"/>
<path d="M7,12L17,12"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 403 B

After

Width:  |  Height:  |  Size: 290 B

Loading…
Cancel
Save