commit fa505923efd6175d5b239f50ec6abbcee97832cf
parent a5e6cff688200e34f2609cc2ca4034f601bf2d50
Author: triesap <137732411+triesap@users.noreply.github.com>
Date: Thu, 29 Aug 2024 11:21:20 +0000
Add nav, add layout view, edit layout trellis
Diffstat:
8 files changed, 504 insertions(+), 350 deletions(-)
diff --git a/src/lib/components/layout-trellis.svelte b/src/lib/components/layout-trellis.svelte
@@ -5,6 +5,6 @@
</script>
-<div class={`flex flex-col w-full mb-4 pt-20 pb-h_tabs_lg px-4 gap-4 justify-start items-start overflow-y-scroll scroll-hide`}>
+<div class={`flex flex-col w-full pt-2 px-4 pb-6 gap-4`}>
{@render children()}
</div>
diff --git a/src/lib/components/layout-view.svelte b/src/lib/components/layout-view.svelte
@@ -0,0 +1,37 @@
+<script lang="ts">
+ import { app_layout, app_nav_blur, app_nav_visible, app_tabs_blur, app_tabs_visible } from "$lib/stores";
+ import { type AppLayoutKey, type PropChildren } from "@radroots/svelte-lib";
+
+ const styles: Record<AppLayoutKey, string> = {
+ base: 'pt-2',
+ lg:'pt-16'
+ };
+
+ let { children }: PropChildren = $props();
+
+ let el: HTMLElement | null;
+
+ let classes_nav = $derived($app_nav_visible ? `pt-h_nav_${$app_layout}` : `${styles[$app_layout]}`)
+ let classes_tabs = $derived($app_tabs_visible ? `pb-h_tabs_${$app_layout}` : ``)
+
+ const scrollChange = (): void => {
+ if (Math.max(el?.scrollTop || 0, 0) > 10) app_nav_blur.set(true);
+ else app_nav_blur.set(false);
+
+ if (Math.max(el?.scrollTop || 0, 0) > 10) app_tabs_blur.set(true);
+ else app_tabs_blur.set(false);
+ };
+
+ $effect(() => {
+ el?.addEventListener("scroll", scrollChange);
+
+ return () => el?.removeEventListener("scroll", scrollChange);
+ });
+</script>
+
+<div
+ bind:this={el}
+ class={`absolute top-0 left-0 flex flex-col h-[100vh] w-full overflow-y-scroll scroll-hide ${classes_nav} ${classes_tabs}`}
+>
+ {@render children()}
+</div>
diff --git a/src/lib/components/nav.svelte b/src/lib/components/nav.svelte
@@ -0,0 +1,94 @@
+<script lang="ts">
+ import { goto } from "$app/navigation";
+ import { app_layout, app_nav, app_nav_blur } from "$lib/stores";
+ import {
+ encode_qp,
+ fill as Fill,
+ glyph as Glyph,
+ } from "@radroots/svelte-lib";
+
+ let el: HTMLElement | null;
+ let el_inner: HTMLElement | null;
+
+ let previous_route = $state(``);
+ let previous_param = $state(``);
+ let previous_label = $state(``);
+
+ let title_label = $state(``);
+
+ app_nav.subscribe((app_nav) => {
+ if (app_nav.length) {
+ const previous = app_nav[app_nav.length - 1];
+ if (previous) {
+ previous_route = previous.route;
+ if (previous.label) previous_label = previous.label;
+ if (previous.params)
+ previous_param = encode_qp(previous.params);
+ }
+ }
+ });
+
+ const handle_previous = async (): Promise<void> => {
+ try {
+ const url = `${previous_route || `/`}${previous_param || ``}`;
+ await goto(url);
+ } catch (e) {
+ console.log(`(error) handle_previous `, e);
+ }
+ };
+</script>
+
+<div
+ bind:this={el}
+ class={`z-10 absolute top-0 left-0 flex flex-col w-full justify-start items-start transition-all duration-[250ms] h-nav_${$app_layout} ${$app_nav_blur ? `bg-layer-0-surface-blur/30 backdrop-blur-md` : ``}`}
+>
+ <div
+ bind:this={el_inner}
+ class={`relative flex flex-col h-full w-full justify-end items-center bg-transparent`}
+ >
+ <div
+ class={`absolute bottom-[5px] left-0 grid grid-cols-12 flex flex-row h-8 w-full justify-start items-center`}
+ >
+ <button
+ class={`col-span-4 flex flex-row h-full pl-2 justify-start items-center`}
+ onclick={async () => {
+ await handle_previous();
+ }}
+ >
+ <Glyph
+ basis={{
+ key: `caret-left`,
+ weight: `bold`,
+ dim: `md+`,
+ classes: `text-layer-1-glyph-hl group-active:opacity-70 transition-opacity`,
+ }}
+ />
+ {#if previous_label}
+ <p
+ class={`font-sans text-navPrevious text-layer-1-glyph-hl group-active:opacity-60 transition-opacity`}
+ >
+ {previous_label}
+ </p>
+ {:else}
+ <Fill />
+ {/if}
+ </button>
+ <div
+ class={`col-span-4 flex flex-row h-full justify-center items-center`}
+ >
+ {#if title_label}
+ <p class={`font-sans text-navCurrent text-layer-1-glyph`}>
+ {title_label}
+ </p>
+ {:else}
+ <Fill />
+ {/if}
+ </div>
+ <div
+ class={`col-span-4 flex flex-row h-full justify-end items-center`}
+ >
+ <Fill />
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte
@@ -1,7 +1,8 @@
<script lang="ts">
import { goto } from "$app/navigation";
+ import Nav from "$lib/components/nav.svelte";
import Tabs from "$lib/components/tabs.svelte";
- import { app_layout } from "$lib/stores";
+ import { app_layout, app_nav_visible, app_tabs_visible } from "$lib/stores";
import { type PropChildren } from "@radroots/svelte-lib";
let { children }: PropChildren = $props();
@@ -9,38 +10,42 @@
</script>
{@render children()}
-<Tabs
-basis={{
- tab_active,
- app_layout: $app_layout,
- list: [
- {
- icon: `house-line`,
- callback: async (tab_i) => {
- tab_active = tab_i;
- await goto("/");
- },
- },
- {
- icon: `key`,
- callback: async (tab_i) => {
- tab_active = tab_i;
- },
- },
- {
- icon: `network`,
- callback: async (tab_i) => {
- tab_active = tab_i;
- },
- },
- {
- icon: `bell-simple`,
- callback: async (tab_i) => {
- tab_active = tab_i;
- await goto("/settings");
- },
- },
- ],
-}}
-/>
-
+{#if $app_nav_visible}
+ <Nav />
+{/if}
+{#if $app_tabs_visible}
+ <Tabs
+ basis={{
+ tab_active,
+ app_layout: $app_layout,
+ list: [
+ {
+ icon: `house-line`,
+ callback: async (tab_i) => {
+ tab_active = tab_i;
+ await goto("/");
+ },
+ },
+ {
+ icon: `key`,
+ callback: async (tab_i) => {
+ tab_active = tab_i;
+ },
+ },
+ {
+ icon: `network`,
+ callback: async (tab_i) => {
+ tab_active = tab_i;
+ },
+ },
+ {
+ icon: `bell-simple`,
+ callback: async (tab_i) => {
+ tab_active = tab_i;
+ await goto("/settings");
+ },
+ },
+ ],
+ }}
+ />
+{/if}
diff --git a/src/routes/(app)/+page.svelte b/src/routes/(app)/+page.svelte
@@ -1,7 +1,13 @@
<script lang="ts">
import { goto } from "$app/navigation";
import { cl } from "$lib/client";
+ import { app_nav_visible, app_tabs_visible } from "$lib/stores";
import { t } from "@radroots/svelte-lib";
+
+ $effect(() => {
+ app_nav_visible.set(false);
+ app_tabs_visible.set(true);
+ });
</script>
<div class={`flex flex-col w-full pt-16 gap-8 justify-center items-center`}>
diff --git a/src/routes/(app)/models/location-gcs/+page.svelte b/src/routes/(app)/models/location-gcs/+page.svelte
@@ -124,7 +124,7 @@
{#each locations_all as location}
<div class={`flex flex-col justify-center items-center`}>
<pre
- class={`glyph font-sans font-[400] text-layer-0-glyph`}>{JSON.stringify(
+ class={`font-sans font-[400] text-layer-0-glyph`}>{JSON.stringify(
location,
null,
4,
@@ -132,7 +132,7 @@
</div>
{/each}
{:else}
- <p class={`glyph font-sans font-[400] text-layer-0-glyph`}>
+ <p class={`font-sans font-[400] text-layer-0-glyph`}>
{"No locations saved"}
</p>
{/if}
diff --git a/src/routes/(app)/settings/+page.svelte b/src/routes/(app)/settings/+page.svelte
@@ -2,372 +2,378 @@
import { goto } from "$app/navigation";
import { cl } from "$lib/client";
import LayoutTrellis from "$lib/components/layout-trellis.svelte";
+ import LayoutView from "$lib/components/layout-view.svelte";
import { _cf } from "$lib/conf";
- import { app_thc } from "$lib/stores";
- import { toggle_color_mode, trellis } from "@radroots/svelte-lib";
+ import { app_nav_visible, app_tabs_visible, app_thc } from "$lib/stores";
+ import {
+ toggle_color_mode,
+ trellis as Trellis,
+ } from "@radroots/svelte-lib";
+
+ $effect(() => {
+ app_nav_visible.set(true);
+ app_tabs_visible.set(false);
+ });
</script>
-<svelte:component this={LayoutTrellis}>
- <svelte:component
- this={trellis}
- basis={{
- args: {
- layer: 1,
- title: {
- value: `Appearance`,
- },
- list: [
- {
- offset: {
- mod: {
- key: `caret-left`,
- },
- },
- touch: {
- label: {
- left: [
- {
- value: "Back",
- },
- ],
- },
- callback: async () => {
- await goto(`/`);
- },
- },
+<LayoutView>
+ <LayoutTrellis>
+ <Trellis
+ basis={{
+ args: {
+ layer: 1,
+ title: {
+ value: `Appearance`,
},
- {
- hide_active: true,
- touch: {
- label: {
- left: [
- {
- value: `Toggle Color Mode (${toggle_color_mode($app_thc)})`,
- classes: `capitalize`,
- },
- ],
+ list: [
+ {
+ offset: {
+ mod: {
+ key: `caret-left`,
+ },
},
- callback: async () => {
- await cl.haptics.impact();
- app_thc.set(toggle_color_mode($app_thc));
+ touch: {
+ label: {
+ left: [
+ {
+ value: "Back",
+ },
+ ],
+ },
+ callback: async () => {
+ await goto(`/`);
+ },
},
},
- },
- ],
- },
- }}
- />
- <svelte:component
- this={trellis}
- basis={{
- args: {
- layer: 1,
- title: {
- value: `Nostr Keys`,
- },
- list: [
- {
- touch: {
- label: {
- left: [
- {
- value: `Nostr Key (public)`,
- classes: `capitalize`,
- },
- ],
- },
- end: {
- icon: {
- key: `caret-right`,
+ {
+ hide_active: true,
+ touch: {
+ label: {
+ left: [
+ {
+ value: `Toggle Color Mode (${toggle_color_mode($app_thc)})`,
+ classes: `capitalize`,
+ },
+ ],
+ },
+ callback: async () => {
+ await cl.haptics.impact();
+ app_thc.set(toggle_color_mode($app_thc));
},
- },
- callback: async () => {
- const public_key = await cl.preferences.get(
- _cf.pref_key_active,
- );
- await cl.dialog.alert(
- `Hi! This is your nostr public key ${public_key}`,
- );
},
},
+ ],
+ },
+ }}
+ />
+ <Trellis
+ basis={{
+ args: {
+ layer: 1,
+ title: {
+ value: `Nostr Keys`,
},
- {
- touch: {
- label: {
- left: [
- {
- value: `Nostr Key (secret)`,
- classes: `capitalize`,
+ list: [
+ {
+ touch: {
+ label: {
+ left: [
+ {
+ value: `Nostr Key (public)`,
+ classes: `capitalize`,
+ },
+ ],
+ },
+ end: {
+ icon: {
+ key: `caret-right`,
},
- ],
- },
- end: {
- icon: {
- key: `caret-right`,
},
- },
- callback: async () => {
- const public_key = await cl.preferences.get(
- _cf.pref_key_active,
- );
- const secret_key = await cl.keystore.get(
- `nostr:key:${public_key}`,
- );
- await cl.dialog.alert(
- `Hi! This is your nostr secret key ${secret_key}`,
- );
+ callback: async () => {
+ const public_key = await cl.preferences.get(
+ _cf.pref_key_active,
+ );
+ await cl.dialog.alert(
+ `Hi! This is your nostr public key ${public_key}`,
+ );
+ },
},
},
- },
- ],
- },
- }}
- />
- <svelte:component
- this={trellis}
- basis={{
- args: {
- layer: 1,
- title: {
- value: `Configuration`,
- },
- list: [
- {
- touch: {
- label: {
- left: [
- {
- value: `Reset Device`,
- classes: `capitalize`,
+ {
+ touch: {
+ label: {
+ left: [
+ {
+ value: `Nostr Key (secret)`,
+ classes: `capitalize`,
+ },
+ ],
+ },
+ end: {
+ icon: {
+ key: `caret-right`,
},
- ],
- },
- end: {
- icon: {
- key: `caret-right`,
},
- },
- callback: async () => {
- const confirm = await cl.dialog.confirm(
- `Hi! This will delete your saved keys.`,
- );
- if (confirm) {
+ callback: async () => {
const public_key = await cl.preferences.get(
_cf.pref_key_active,
);
- await cl.keystore.remove(
+ const secret_key = await cl.keystore.get(
`nostr:key:${public_key}`,
);
- await cl.preferences.remove(
- _cf.pref_key_active,
+ await cl.dialog.alert(
+ `Hi! This is your nostr secret key ${secret_key}`,
);
- await cl.window.splash_show();
- location.reload();
- }
+ },
},
},
- },
- ],
- },
- }}
- />
- <svelte:component
- this={trellis}
- basis={{
- args: {
- layer: 1,
- title: {
- value: `Share`,
+ ],
},
- list: [
- {
- touch: {
- label: {
- left: [
- {
- value: `Geolocation Current`,
- classes: `capitalize`,
+ }}
+ />
+ <Trellis
+ basis={{
+ args: {
+ layer: 1,
+ title: {
+ value: `Configuration`,
+ },
+ list: [
+ {
+ touch: {
+ label: {
+ left: [
+ {
+ value: `Reset Device`,
+ classes: `capitalize`,
+ },
+ ],
+ },
+ end: {
+ icon: {
+ key: `caret-right`,
},
- ],
- },
- callback: async () => {
- const pos = await cl.geo.current();
- await cl.dialog.alert(JSON.stringify(pos));
+ },
+ callback: async () => {
+ const confirm = await cl.dialog.confirm(
+ `Hi! This will delete your saved keys.`,
+ );
+ if (confirm) {
+ const public_key =
+ await cl.preferences.get(
+ _cf.pref_key_active,
+ );
+ await cl.keystore.remove(
+ `nostr:key:${public_key}`,
+ );
+ await cl.preferences.remove(
+ _cf.pref_key_active,
+ );
+ await cl.window.splash_show();
+ location.reload();
+ }
+ },
},
},
- },
- ],
- },
- }}
- />
- <svelte:component
- this={trellis}
- basis={{
- args: {
- layer: 1,
- title: {
- value: `Haptics`,
+ ],
},
- list: [
- {
- touch: {
- label: {
- left: [
- {
- value: `Haptics Touch (less)`,
- classes: `capitalize`,
- },
- ],
- },
- end: {
- icon: {
- key: `caret-right`,
+ }}
+ />
+ <Trellis
+ basis={{
+ args: {
+ layer: 1,
+ title: {
+ value: `Share`,
+ },
+ list: [
+ {
+ touch: {
+ label: {
+ left: [
+ {
+ value: `Geolocation Current`,
+ classes: `capitalize`,
+ },
+ ],
+ },
+ callback: async () => {
+ const pos = await cl.geo.current();
+ await cl.dialog.alert(JSON.stringify(pos));
},
- },
- callback: async () => {
- await cl.haptics.impact("less");
},
},
+ ],
+ },
+ }}
+ />
+ <Trellis
+ basis={{
+ args: {
+ layer: 1,
+ title: {
+ value: `Haptics`,
},
- {
- touch: {
- label: {
- left: [
- {
- value: `Haptics Touch (more)`,
- classes: `capitalize`,
+ list: [
+ {
+ touch: {
+ label: {
+ left: [
+ {
+ value: `Haptics Touch (less)`,
+ classes: `capitalize`,
+ },
+ ],
+ },
+ end: {
+ icon: {
+ key: `caret-right`,
},
- ],
- },
- end: {
- icon: {
- key: `caret-right`,
},
- },
- callback: async () => {
- await cl.haptics.impact("more");
+ callback: async () => {
+ await cl.haptics.impact("less");
+ },
},
},
- },
- {
- touch: {
- label: {
- left: [
- {
- value: `Haptics Vibrate (500ms)`,
- classes: `capitalize`,
+ {
+ touch: {
+ label: {
+ left: [
+ {
+ value: `Haptics Touch (more)`,
+ classes: `capitalize`,
+ },
+ ],
+ },
+ end: {
+ icon: {
+ key: `caret-right`,
},
- ],
- },
- end: {
- icon: {
- key: `caret-right`,
},
- },
- callback: async () => {
- await cl.haptics.vibrate(500);
+ callback: async () => {
+ await cl.haptics.impact("more");
+ },
},
},
- },
- {
- touch: {
- label: {
- left: [
- {
- value: `Haptics Selection Start`,
- classes: `capitalize`,
+ {
+ touch: {
+ label: {
+ left: [
+ {
+ value: `Haptics Vibrate (500ms)`,
+ classes: `capitalize`,
+ },
+ ],
+ },
+ end: {
+ icon: {
+ key: `caret-right`,
},
- ],
- },
- end: {
- icon: {
- key: `caret-right`,
},
- },
- callback: async () => {
- await cl.haptics.selection_start();
+ callback: async () => {
+ await cl.haptics.vibrate(500);
+ },
},
},
- },
- {
- touch: {
- label: {
- left: [
- {
- value: `Haptics Selection End`,
- classes: `capitalize`,
+ {
+ touch: {
+ label: {
+ left: [
+ {
+ value: `Haptics Selection Start`,
+ classes: `capitalize`,
+ },
+ ],
+ },
+ end: {
+ icon: {
+ key: `caret-right`,
},
- ],
- },
- end: {
- icon: {
- key: `caret-right`,
},
- },
- callback: async () => {
- await cl.haptics.selection_end();
+ callback: async () => {
+ await cl.haptics.selection_start();
+ },
},
},
- },
- ],
- },
- }}
- />
- <svelte:component
- this={trellis}
- basis={{
- args: {
- layer: 1,
- title: {
- value: `Share`,
- },
- list: [
- {
- touch: {
- label: {
- left: [
- {
- value: `Share Test #1`,
- classes: `capitalize`,
+ {
+ touch: {
+ label: {
+ left: [
+ {
+ value: `Haptics Selection End`,
+ classes: `capitalize`,
+ },
+ ],
+ },
+ end: {
+ icon: {
+ key: `caret-right`,
},
- ],
- },
- callback: async () => {
- const res = await cl.share.open({
- title: `Radroots Home Page`,
- text: `Find farmers around the world.`,
- url: `https://radroots.org`,
- dialog_title: `This is the dialog title`,
- });
-
- console.log(`res `, res);
+ },
+ callback: async () => {
+ await cl.haptics.selection_end();
+ },
},
},
+ ],
+ },
+ }}
+ />
+ <Trellis
+ basis={{
+ args: {
+ layer: 1,
+ title: {
+ value: `Share`,
},
- {
- touch: {
- label: {
- left: [
- {
- value: `Share Test #2`,
- classes: `capitalize`,
- },
- ],
+ list: [
+ {
+ touch: {
+ label: {
+ left: [
+ {
+ value: `Share Test #1`,
+ classes: `capitalize`,
+ },
+ ],
+ },
+ callback: async () => {
+ const res = await cl.share.open({
+ title: `Radroots Home Page`,
+ text: `Find farmers around the world.`,
+ url: `https://radroots.org`,
+ dialog_title: `This is the dialog title`,
+ });
+
+ console.log(`res `, res);
+ },
},
- callback: async () => {
- const res = await cl.share.open({
- title: `Radroots Home Page`,
- url: `https://radroots.org`,
- dialog_title: `This is the dialog title`,
- files: [`file-1.png`, `file-2.png`],
- });
+ },
+ {
+ touch: {
+ label: {
+ left: [
+ {
+ value: `Share Test #2`,
+ classes: `capitalize`,
+ },
+ ],
+ },
+ callback: async () => {
+ const res = await cl.share.open({
+ title: `Radroots Home Page`,
+ url: `https://radroots.org`,
+ dialog_title: `This is the dialog title`,
+ files: [`file-1.png`, `file-2.png`],
+ });
- console.log(`res `, res);
+ console.log(`res `, res);
+ },
},
},
- },
- ],
- },
- }}
- />
-</svelte:component>
+ ],
+ },
+ }}
+ />
+ </LayoutTrellis>
+</LayoutView>
diff --git a/tailwind.config.ts b/tailwind.config.ts
@@ -8,6 +8,8 @@ const heights = {
line: `46px`,
tabs_base: `64px`,
tabs_lg: `88px`,
+ nav_base: `64px`,
+ nav_lg: `100px`,
};
const widths = {
@@ -32,6 +34,10 @@ const config: Config = {
fontSize: {
line: ["1.05rem", { lineHeight: "1.33rem", fontWeight: 300 }],
trellisTitle: ["0.8rem", { lineHeight: "1rem", fontWeight: 200 }],
+ trellisLine: ["1.05rem", { lineHeight: "1.33rem", fontWeight: 300 }],
+ trellisLabel: ["0.8rem", { lineHeight: "1rem", fontWeight: 200 }],
+ navPrevious: ["1.09rem", { lineHeight: "1.33rem", fontWeight: 400 }],
+ navCurrent: ["1.09rem", { lineHeight: "1.33rem", fontWeight: 500 }],
},
height: {
...heights,