Site examples: add a cache and show a loading icon

Add a loading icon I made in SVG: it uses SMIL animation so it might not be well supported on IE/Edge but I think Edge will be powered by Chromium pretty soon.

Also set the REPL orientation based on the width as discussed in #2466

Closes #2527
pull/2529/head
Luca Bonavita 5 years ago
parent 6c0aa3b9ef
commit ce5399a1de

@ -1,6 +1,7 @@
<script>
export let sections = [];
export let active_section = null;
export let isLoading = false;
</script>
<style>
@ -50,6 +51,12 @@
color: white;
}
a.active.loading {
background: rgba(255, 255, 255, 0.1) calc(100% - 3rem) 50% no-repeat url(/icons/loading.svg);
background-size: 1em 1em;
color: white;
}
.thumbnail {
background-color: white;
object-fit: contain;
@ -73,6 +80,7 @@
href="examples#{example.slug}"
class="row"
class:active="{example.slug === active_section}"
class:loading="{isLoading}"
>
<img
class="thumbnail"

@ -21,7 +21,7 @@
import ScreenToggle from '../../components/ScreenToggle.svelte';
import {
mapbox_setup, // needed for context API example
mapbox_setup, // see site/content/examples/15-context/00-context-api
rollupUrl,
svelteUrl
} from '../../config';
@ -36,32 +36,47 @@
let width;
let offset = 1;
let repl;
let isLoading = false;
let cache = {};
$: title = title_by_slug[active_slug] || '';
$: first_slug = sections[0].examples[0].slug;
$: if (repl) {
fetch(`examples/${active_slug}.json`)
.then(async response => {
if (response.ok) {
const data = await response.json();
repl.set({
components: process_example(data.files)
});
}
});
}
$: mobile = width < 768; // note: same as per media query below
$: replOrientation = (mobile || width > 1080) ? 'columns' : 'rows';
$: if (repl && active_slug) {
if (active_slug in cache) {
repl.set({ components: cache[active_slug] });
offset = 1;
} else {
isLoading = true;
fetch(`examples/${active_slug}.json`)
.then(async response => {
if (response.ok) {
const {files} = await response.json();
return process_example(files);
}
})
.then(components => {
cache[active_slug] = components;
repl.set({components});
offset = 1;
isLoading = false;
})
.catch(function(error) {
isLoading = false;
});
}
}
onMount(() => {
const onhashchange = () => {
active_slug = getFragment();
offset = 1;
};
window.addEventListener('hashchange', onhashchange, false);
if (getFragment()) {
active_slug = getFragment();
const fragment = getFragment();
if (fragment) {
active_slug = fragment;
} else {
active_slug = first_slug;
goto(`examples#${active_slug}`);
@ -82,17 +97,21 @@
</svelte:head>
<div class='examples-container' bind:clientWidth={width}>
<div class="viewport offset-{offset}">
<TableOfContents {sections} active_section={active_slug} />
<Repl
bind:this={repl}
{svelteUrl}
{rollupUrl}
orientation={mobile ? 'columns' : 'rows'}
fixed={mobile}
relaxed
injectedJS={mapbox_setup}
/>
<div
class="viewport offset-{offset}"
>
<TableOfContents {sections} active_section={active_slug} {isLoading} />
<div class="toc" class:loading={isLoading}>
<Repl
bind:this={repl}
{svelteUrl}
{rollupUrl}
orientation={replOrientation}
fixed={mobile}
relaxed
injectedJS={mapbox_setup}
/>
</div>
</div>
{#if mobile}
<ScreenToggle bind:offset labels={['index', 'input', 'output']}/>
@ -117,6 +136,10 @@
grid-auto-rows: 100%;
}
.toc.loading {
opacity: 0.6;
}
.offset-1 { transform: translate(-33.333%, 0); }
.offset-2 { transform: translate(-66.666%, 0); }

@ -0,0 +1,6 @@
<?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">
<circle id="spinner" cx="12" cy="12" r="8" fill="none" stroke="white" stroke-width="3" stroke-dasharray="50.2 50" />
<animate href="#spinner" attributeName="stroke-dashoffset" values="52;0;52" dur="5s" repeatCount="indefinite" />
<animateTransform href="#spinner" attributeName="transform" type="rotate" values="0 12 12;360 12 12;0 12 12" dur="9s" repeatCount="indefinite"/>
</svg>

After

Width:  |  Height:  |  Size: 519 B

Loading…
Cancel
Save