Skip to content

Commit 5dc6344

Browse files
Implement backward and forward navigation options to iframed window
1 parent 9c9656b commit 5dc6344

File tree

6 files changed

+113
-21
lines changed

6 files changed

+113
-21
lines changed

pnpm-lock.yaml

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/routes/tutorial/[slug]/+page.svelte

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@
9595
9696
/** @type {import('$lib/types').Adapter | undefined} */
9797
let adapter;
98+
/** @type {string[]} */
99+
let history_bwd = [];
100+
/** @type {string[]} */
101+
let history_fwd = [];
102+
let ignore_path_change = false;
98103
99104
onMount(() => {
100105
function destroy() {
@@ -254,7 +259,16 @@
254259
if (e.origin !== adapter.base) return;
255260
256261
if (e.data.type === 'ping') {
257-
path = e.data.data.path ?? path;
262+
const new_path = e.data.data.path ?? path;
263+
if (path !== new_path) {
264+
// skip `nav_to` step if triggered by bwd/fwd action
265+
if (ignore_path_change) {
266+
ignore_path_change = false;
267+
} else {
268+
nav_to();
269+
}
270+
path = new_path;
271+
}
258272
259273
clearTimeout(timeout);
260274
timeout = setTimeout(() => {
@@ -301,6 +315,42 @@
301315
iframe.src = src;
302316
parentNode?.appendChild(iframe);
303317
}
318+
319+
/** @param {string} path */
320+
function route_to(path) {
321+
if (adapter) {
322+
const url = new URL(path, adapter.base);
323+
path = url.pathname + url.search + url.hash;
324+
set_iframe_src(adapter.base + path);
325+
}
326+
}
327+
328+
/** @param {string | null} new_path */
329+
function nav_to(new_path = null) {
330+
if (path !== history_bwd[history_bwd.length - 1]) {
331+
history_bwd = [...history_bwd, path];
332+
}
333+
history_fwd = [];
334+
if (new_path) route_to(new_path);
335+
}
336+
337+
function go_bwd() {
338+
const new_path = history_bwd[history_bwd.length - 1];
339+
if (new_path) {
340+
ignore_path_change = true;
341+
[history_bwd, history_fwd] = [history_bwd.slice(0, -1), [path, ...history_fwd]];
342+
route_to(new_path);
343+
}
344+
}
345+
346+
function go_fwd() {
347+
const new_path = history_fwd[0];
348+
if (new_path) {
349+
ignore_path_change = true;
350+
[history_bwd, history_fwd] = [[...history_bwd, path], history_fwd.slice(1)];
351+
route_to(new_path);
352+
}
353+
}
304354
</script>
305355
306356
<svelte:window on:message={handle_message} bind:innerWidth={width} />
@@ -400,20 +450,18 @@
400450
401451
<section slot="b" class="preview">
402452
<Chrome
453+
{history_bwd}
454+
{history_fwd}
403455
{path}
404456
{loading}
405457
on:refresh={() => {
406458
if (adapter) {
407459
set_iframe_src(adapter.base + path);
408460
}
409461
}}
410-
on:change={(e) => {
411-
if (adapter) {
412-
const url = new URL(e.detail.value, adapter.base);
413-
path = url.pathname + url.search + url.hash;
414-
set_iframe_src(adapter.base + path);
415-
}
416-
}}
462+
on:change={(e) => nav_to(e.detail.value)}
463+
on:back={go_bwd}
464+
on:forward={go_fwd}
417465
/>
418466
419467
<div class="content">

src/routes/tutorial/[slug]/Chrome.svelte

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,34 @@
11
<script>
22
import { createEventDispatcher } from 'svelte';
3+
import back from './back.svg';
4+
import forward from './forward.svg';
35
import refresh from './refresh.svg';
46
57
/** @type {string} */
68
export let path;
79
10+
/** @type {string[]} */
11+
export let history_bwd = [];
12+
13+
/** @type {string[]} */
14+
export let history_fwd = [];
15+
816
/** @type {boolean} */
917
export let loading;
1018
1119
const dispatch = createEventDispatcher();
20+
21+
$: [disabledBwd, disabledFwd] = [loading || !history_bwd.length, loading || !history_fwd.length];
1222
</script>
1323

1424
<div class="chrome">
15-
<button disabled={loading} on:click={() => dispatch('refresh')} aria-label="reload">
25+
<button disabled={disabledBwd} on:click={() => dispatch('back')} aria-label="go back">
26+
<img src={back} alt="Back icon" />
27+
</button>
28+
<button disabled={disabledFwd} on:click={() => dispatch('forward')} aria-label="go forward">
29+
<img src={forward} alt="Forward icon" />
30+
</button>
31+
<button class="refresh" disabled={loading} on:click={() => dispatch('refresh')} aria-label="reload">
1632
<img src={refresh} alt="Reload icon" />
1733
</button>
1834

@@ -43,11 +59,11 @@
4359
.chrome button img {
4460
width: 2rem;
4561
height: 2rem;
46-
transition: 0.2s ease-out;
62+
transition: transform 0.2s ease-out, opacity 0.1s ease-out;
4763
transform: none;
4864
}
4965
50-
.chrome button:active img {
66+
.chrome button.refresh:active img {
5167
transform: rotate(-360deg);
5268
transition: none;
5369
}
@@ -71,4 +87,26 @@
7187
outline: none;
7288
border: 2px solid var(--sk-theme-3);
7389
}
90+
91+
.chrome button {
92+
user-select: none;
93+
}
94+
95+
.chrome button[disabled] {
96+
opacity: 1;
97+
}
98+
99+
.chrome button[disabled] img {
100+
opacity: .2;
101+
}
102+
103+
.chrome button img {
104+
opacity: .6;
105+
}
106+
107+
.chrome button:hover img,
108+
.chrome button:active img,
109+
.chrome button:focus-visible img {
110+
opacity: 1;
111+
}
74112
</style>

src/routes/tutorial/[slug]/back.svg

Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 2 additions & 2 deletions
Loading

0 commit comments

Comments
 (0)