add transition to nav tree
user-agent detection is employed to ensure that the SSR renders the nav items by default for desktop (opposite for mobile). CSS media queries take over after the content loads on the device. TODO: fix preview pane jump on desktop
This commit is contained in:
parent
890f8c6c17
commit
8ac0f6b931
63
package-lock.json
generated
63
package-lock.json
generated
@ -7,11 +7,16 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "resumarkdown",
|
"name": "resumarkdown",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
|
"dependencies": {
|
||||||
|
"ua-parser-js": "^1.0.39"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "^1.28.1",
|
"@playwright/test": "^1.28.1",
|
||||||
"@sveltejs/adapter-auto": "^3.0.0",
|
"@sveltejs/adapter-auto": "^3.0.0",
|
||||||
"@sveltejs/kit": "^2.0.0",
|
"@sveltejs/kit": "^2.0.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||||
|
"@types/ua-parser-js": "^0.7.39",
|
||||||
|
"@types/user-agents": "^1.0.4",
|
||||||
"less": "^4.2.0",
|
"less": "^4.2.0",
|
||||||
"prettier": "^3.1.1",
|
"prettier": "^3.1.1",
|
||||||
"prettier-plugin-svelte": "^3.1.2",
|
"prettier-plugin-svelte": "^3.1.2",
|
||||||
@ -19,6 +24,7 @@
|
|||||||
"svelte-check": "^4.0.0",
|
"svelte-check": "^4.0.0",
|
||||||
"svelte-preprocess": "^6.0.3",
|
"svelte-preprocess": "^6.0.3",
|
||||||
"typescript": "^5.0.0",
|
"typescript": "^5.0.0",
|
||||||
|
"user-agents": "^1.1.325",
|
||||||
"vite": "^5.0.3",
|
"vite": "^5.0.3",
|
||||||
"vitest": "^2.0.0"
|
"vitest": "^2.0.0"
|
||||||
}
|
}
|
||||||
@ -829,6 +835,20 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/ua-parser-js": {
|
||||||
|
"version": "0.7.39",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.39.tgz",
|
||||||
|
"integrity": "sha512-P/oDfpofrdtF5xw433SPALpdSchtJmY7nsJItf8h3KXqOslkbySh8zq4dSWXH2oTjRvJ5PczVEoCZPow6GicLg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@types/user-agents": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/user-agents/-/user-agents-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-AjeFc4oX5WPPflgKfRWWJfkEk7Wu82fnj1rROPsiqFt6yElpdGFg8Srtm/4PU4rA9UiDUZlruGPgcwTMQlwq4w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@vitest/expect": {
|
"node_modules/@vitest/expect": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.2.tgz",
|
||||||
@ -1357,6 +1377,13 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash.clonedeep": {
|
||||||
|
"version": "4.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
||||||
|
"integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/loupe": {
|
"node_modules/loupe": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz",
|
||||||
@ -1986,6 +2013,42 @@
|
|||||||
"node": ">=14.17"
|
"node": ">=14.17"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ua-parser-js": {
|
||||||
|
"version": "1.0.39",
|
||||||
|
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.39.tgz",
|
||||||
|
"integrity": "sha512-k24RCVWlEcjkdOxYmVJgeD/0a1TiSpqLg+ZalVGV9lsnr4yqu0w7tX/x2xX6G4zpkgQnRf89lxuZ1wsbjXM8lw==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/ua-parser-js"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "paypal",
|
||||||
|
"url": "https://paypal.me/faisalman"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/faisalman"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"ua-parser-js": "script/cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/user-agents": {
|
||||||
|
"version": "1.1.325",
|
||||||
|
"resolved": "https://registry.npmjs.org/user-agents/-/user-agents-1.1.325.tgz",
|
||||||
|
"integrity": "sha512-BmVDscJOZsBBztMPHg+wf65QwbT+N3C46YEsuW8BmcxRxwKh2AbdSaKEjzoC7rDlyuECXEUXO+C2eW3QAhbl2A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"lodash.clonedeep": "^4.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "5.4.8",
|
"version": "5.4.8",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz",
|
||||||
|
@ -14,11 +14,16 @@
|
|||||||
"lint": "prettier --check .",
|
"lint": "prettier --check .",
|
||||||
"format": "prettier --write ."
|
"format": "prettier --write ."
|
||||||
},
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ua-parser-js": "^1.0.39"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "^1.28.1",
|
"@playwright/test": "^1.28.1",
|
||||||
"@sveltejs/adapter-auto": "^3.0.0",
|
"@sveltejs/adapter-auto": "^3.0.0",
|
||||||
"@sveltejs/kit": "^2.0.0",
|
"@sveltejs/kit": "^2.0.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||||
|
"@types/ua-parser-js": "^0.7.39",
|
||||||
|
"@types/user-agents": "^1.0.4",
|
||||||
"less": "^4.2.0",
|
"less": "^4.2.0",
|
||||||
"prettier": "^3.1.1",
|
"prettier": "^3.1.1",
|
||||||
"prettier-plugin-svelte": "^3.1.2",
|
"prettier-plugin-svelte": "^3.1.2",
|
||||||
@ -26,6 +31,7 @@
|
|||||||
"svelte-check": "^4.0.0",
|
"svelte-check": "^4.0.0",
|
||||||
"svelte-preprocess": "^6.0.3",
|
"svelte-preprocess": "^6.0.3",
|
||||||
"typescript": "^5.0.0",
|
"typescript": "^5.0.0",
|
||||||
|
"user-agents": "^1.1.325",
|
||||||
"vite": "^5.0.3",
|
"vite": "^5.0.3",
|
||||||
"vitest": "^2.0.0"
|
"vitest": "^2.0.0"
|
||||||
},
|
},
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
import { slide } from 'svelte/transition';
|
||||||
|
|
||||||
import { navHeight } from '$lib/stores/layout';
|
import { navHeight } from '$lib/stores/layout';
|
||||||
|
|
||||||
import NavToggle from './nav-toggle.svelte';
|
import NavToggle from './nav-toggle.svelte';
|
||||||
|
|
||||||
let open: boolean = false;
|
export let mobile: boolean = true;
|
||||||
|
|
||||||
let hidden: boolean;
|
let open: boolean = false;
|
||||||
$: hidden = !open;
|
|
||||||
|
|
||||||
// magic to offset preview pane on desktop
|
// magic to offset preview pane on desktop
|
||||||
let navRef: HTMLElement;
|
let navRef: HTMLElement;
|
||||||
@ -20,9 +20,11 @@
|
|||||||
|
|
||||||
<nav bind:this={navRef}>
|
<nav bind:this={navRef}>
|
||||||
<NavToggle bind:navOpen={open} />
|
<NavToggle bind:navOpen={open} />
|
||||||
<ul class:hidden role="tablist">
|
{#if open || !mobile}
|
||||||
|
<ul role="tablist" transition:slide={{ duration: 300 }}>
|
||||||
<slot />
|
<slot />
|
||||||
</ul>
|
</ul>
|
||||||
|
{/if}
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@ -35,14 +37,10 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
&.hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: @sizes[lg]) {
|
@media screen and (min-width: @sizes[lg]) {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border-right: @border;
|
border-right: @border;
|
||||||
display: flex !important;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-evenly;
|
justify-content: space-evenly;
|
||||||
width: 50%;
|
width: 50%;
|
||||||
|
12
src/routes/+layout.server.ts
Normal file
12
src/routes/+layout.server.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { UAParser } from 'ua-parser-js';
|
||||||
|
|
||||||
|
export async function load({ request }) {
|
||||||
|
const ua = request.headers.get('user-agent');
|
||||||
|
|
||||||
|
if (!ua) {
|
||||||
|
return { mobile: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
const { device } = UAParser(ua);
|
||||||
|
return { mobile: device.type === 'mobile' };
|
||||||
|
}
|
@ -5,6 +5,8 @@
|
|||||||
import NavItem from '$lib/components/nav-item.svelte';
|
import NavItem from '$lib/components/nav-item.svelte';
|
||||||
import NavTree from '$lib/components/nav-tree.svelte';
|
import NavTree from '$lib/components/nav-tree.svelte';
|
||||||
|
|
||||||
|
export let data;
|
||||||
|
|
||||||
let markdown: string = '';
|
let markdown: string = '';
|
||||||
let stylesheet: string = '';
|
let stylesheet: string = '';
|
||||||
</script>
|
</script>
|
||||||
@ -15,7 +17,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<header>
|
<header>
|
||||||
<Headline>resumarkdown</Headline>
|
<Headline>resumarkdown</Headline>
|
||||||
<NavTree>
|
<NavTree mobile={data.mobile}>
|
||||||
<NavItem destination="content">content</NavItem>
|
<NavItem destination="content">content</NavItem>
|
||||||
<NavItem destination="style">style</NavItem>
|
<NavItem destination="style">style</NavItem>
|
||||||
<NavItem destination="preview">preview</NavItem>
|
<NavItem destination="preview">preview</NavItem>
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
import { expect, test } from '@playwright/test';
|
import { expect, test } from '@playwright/test';
|
||||||
|
|
||||||
test.use({ viewport: { height: 2556, width: 1179 } });
|
import UserAgent from 'user-agents';
|
||||||
|
|
||||||
|
test.use({
|
||||||
|
viewport: { height: 2556, width: 1179 },
|
||||||
|
userAgent: new UserAgent({ deviceCategory: 'mobile' }).toString(),
|
||||||
|
});
|
||||||
|
|
||||||
test('mobile page has nav tree hidden by default', async ({ page }) => {
|
test('mobile page has nav tree hidden by default', async ({ page }) => {
|
||||||
await page.goto('/');
|
await page.goto('/');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user