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. Transitions allow elements to enter and leave the DOM gracefully, rather than suddenly appearing and disappearing.
```html ```html
<!-- { title: 'Transitions' } --> <!-- { title: 'Transitions' } -->
<script> <script>
import { fade } from 'svelte/transition.js'; import { fade } from 'svelte/transition';
let visible = false; let visible = false;
</script> </script>
@ -21,12 +19,12 @@ Transitions allow elements to enter and leave the DOM gracefully, rather than su
{/if} {/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 ```html
<!-- { title: 'Transition with parameters' } --> <!-- { title: 'Transition with parameters' } -->
<script> <script>
import { fly } from 'svelte-transitions'; import { fly } from 'svelte/transition';
let visible = false; let visible = false;
</script> </script>
@ -37,6 +35,9 @@ Transitions can have parameters — typically `delay` and `duration`, but often
{/if} {/if}
``` ```
### In and out
An element can have separate `in` and `out` transitions: An element can have separate `in` and `out` transitions:
```html ```html
@ -53,7 +54,27 @@ An element can have separate `in` and `out` transitions:
{/if} {/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 * `duration` — how long the transition takes in milliseconds
* `delay` — milliseconds before the transition starts * `delay` — milliseconds before the transition starts

@ -104,37 +104,8 @@
</symbol> </symbol>
<symbol id="link" class="icon" viewBox="0 0 24 24"> <symbol id="link" class="icon" viewBox="0 0 24 24">
<!-- <path d=" <path d="M9,7L6,7A2 2 0 0 0 6,17L9,17"/>
M10.5,13.5 <path d="M15,7L18,7A2 2 0 0 1 18,17L15,17"/>
C8.5,11.5 9.5,11.5 9.5,10.5 <path d="M7,12L17,12"/>
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
"/>
</symbol> </symbol>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

@ -1,5 +1,5 @@
<script> <script>
import { onMount } from 'svelte'; import { onMount, afterUpdate } from 'svelte';
import Icon from '../../components/Icon.html'; import Icon from '../../components/Icon.html';
export let sections = []; export let sections = [];
@ -36,21 +36,54 @@
window.removeEventListener('hashchange', onhashchange, false); 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> </script>
<ul class='guide-toc'> <ul bind:this={ul} class="guide-toc">
{#each sections as section} {#each sections as section}
<li> <li>
<a class='section {section.slug === active_section ? "active": ""}' href='guide#{section.slug}'> <a class="section" class:active="{section.slug === active_section}" href="guide#{section.slug}">
{section.metadata.title} {#if section.slug === active_section} {section.metadata.title}
<Icon name='arrow-right' /> {/if}
{#if section.slug === active_section}
<Icon name="arrow-right" />
{/if}
</a> </a>
{#each section.subsections as subsection} {#each section.subsections as subsection}
<!-- see <script> below: on:click='scrollTo(event, subsection.slug)' --> <!-- see <script> below: on:click='scrollTo(event, subsection.slug)' -->
<a class='subsection {subsection.slug === active_section ? "active": ""}' href='guide#{subsection.slug}'> <a class="subsection" class:active="{subsection.slug === active_section}" href="guide#{subsection.slug}">
{subsection.title} {#if subsection.slug === active_section} {subsection.title}
<Icon name='arrow-right' /> {/if}
{#if subsection.slug === active_section}
<Icon name="arrow-right" />
{/if}
</a> </a>
{/each} {/each}
</li> </li>

@ -4,7 +4,7 @@ import * as fleece from 'golden-fleece';
import process_markdown from '../../utils/_process_markdown.js'; import process_markdown from '../../utils/_process_markdown.js';
import marked from 'marked'; 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'); require('prismjs/components/prism-bash');
const langs = { const langs = {
@ -34,16 +34,25 @@ const escaped = {
const unescaped = Object.keys(escaped).reduce( const unescaped = Object.keys(escaped).reduce(
(unescaped, key) => ((unescaped[escaped[key]] = key), unescaped), (unescaped, key) => ((unescaped[escaped[key]] = key), unescaped),
{}, {}
); );
function unescape(str) { function unescape(str) {
return String(str).replace(/&.+?;/g, match => unescaped[match] || match); 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) { function extractMeta(line, lang) {
try { try {
@ -83,6 +92,7 @@ export default function() {
const { content, metadata } = process_markdown(markdown); const { content, metadata } = process_markdown(markdown);
const subsections = [];
const groups = []; const groups = [];
let group = null; let group = null;
let uid = 1; let uid = 1;
@ -91,7 +101,7 @@ export default function() {
renderer.code = (source, lang) => { renderer.code = (source, lang) => {
source = source.replace(/^ +/gm, match => source = source.replace(/^ +/gm, match =>
match.split(' ').join('\t'), match.split(' ').join('\t')
); );
const lines = source.split('\n'); const lines = source.split('\n');
@ -140,12 +150,50 @@ export default function() {
const highlighted = Prism.highlight( const highlighted = Prism.highlight(
source, source,
Prism.languages[plang], Prism.languages[plang],
lang, lang
); );
return `<div class='${className}'>${prefix}<pre class='language-${plang}'><code>${highlighted}</code></pre></div>`; 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 => { blockTypes.forEach(type => {
const fn = renderer[type]; const fn = renderer[type];
renderer[type] = function() { renderer[type] = function() {
@ -185,29 +233,10 @@ export default function() {
}; };
}), }),
json5: json5 && json5.source, 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 { return {
html: html.replace(/@@(\d+)/g, (m, id) => hashes[id] || m), html: html.replace(/@@(\d+)/g, (m, id) => hashes[id] || m),
metadata, metadata,

@ -6,7 +6,7 @@
</script> </script>
<script> <script>
import { onMount } from 'svelte'; import { onMount, afterUpdate } from 'svelte';
import GuideContents from './_GuideContents.html'; import GuideContents from './_GuideContents.html';
import Icon from '../../components/Icon.html'; import Icon from '../../components/Icon.html';
@ -18,6 +18,7 @@
let active_section; let active_section;
let container; let container;
let aside;
onMount(() => { onMount(() => {
const anchors = container.querySelectorAll('[id]'); const anchors = container.querySelectorAll('[id]');
@ -148,21 +149,54 @@
margin-top: 0; 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),
.content :global(h3 > code) { .content :global(h3 > code) {
pointer-events: none;
font-weight: 700; font-weight: 700;
font-size: var(--h3); font-size: var(--h3);
color: var(--second); color: var(--second);
padding: 6.4rem 0 1.6rem 0; margin: 6.4rem 0 1.6rem 0;
background: transparent; background: transparent;
line-height: 1;
} }
.content :global(code) { .content :global(code) {
padding: .3rem .8rem .3rem; padding: .3rem .8rem .3rem;
margin: 0 0.2rem; margin: 0 0.2rem;
top: -.1rem; top: -.1rem;
background: #f9f9f9; background: #f4f4f4;
}
.content :global(pre) :global(code) {
padding: 0;
margin: 0;
top: 0;
background: transparent;
} }
.content :global(.icon) { .content :global(.icon) {
@ -194,11 +228,16 @@
section :global(blockquote) { section :global(blockquote) {
color: var(--flash); color: hsl(204, 100%, 50%);
border: 2px solid currentColor; border: 2px solid var(--flash);
padding-left: 8.8rem; padding-left: 8.8rem;
} }
section :global(blockquote) :global(code) {
background: hsl(204, 100%, 95%) !important;
color: hsl(204, 100%, 50%);
}
section :global(blockquote::before) { section :global(blockquote::before) {
content: ' '; content: ' ';
position: absolute; position: absolute;
@ -217,8 +256,11 @@
<div bind:this={container} class='content linkify listify'> <div bind:this={container} class='content linkify listify'>
{#each sections as section} {#each sections as section}
<section id='{section.slug}'> <section data-id={section.slug}>
<h2> <h2>
<span class="offset-anchor" id={section.slug}></span>
<a href="#{section.slug}" class="anchor" aria-hidden></a>
{section.metadata.title} {section.metadata.title}
<small> <small>
<a href='https://github.com/sveltejs/svelte/edit/master/site/content/guide/{section.file}' title='edit this section'> <a href='https://github.com/sveltejs/svelte/edit/master/site/content/guide/{section.file}' title='edit this section'>
@ -230,8 +272,8 @@
{/each} {/each}
</div> </div>
<aside class="sidebar-container"> <aside bind:this={aside} class="sidebar-container">
<div class="sidebar"> <div class="sidebar">
<GuideContents {sections} /> <GuideContents {sections} {active_section} />
</div> </div>
</aside> </aside>

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

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-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"> <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> </svg>

Before

Width:  |  Height:  |  Size: 403 B

After

Width:  |  Height:  |  Size: 290 B

Loading…
Cancel
Save