Superpowered to do lists. No signup required.
1<script lang="ts">
2 import "../app.css";
3 import { onMount, type Snippet } from "svelte";
4 import { page } from "$app/state";
5 import { goto } from "$app/navigation";
6 import { fade } from "svelte/transition";
7 import toast, { Toaster } from "svelte-french-toast";
8 import { persisted, pinned_list } from "$lib/stores.svelte";
9
10 interface Props {
11 children: Snippet
12 }
13
14 let { children }: Props = $props();
15
16 let theme = persisted<string>("theme", "dark");
17 let is_menu_open = $state(false);
18 let theme_style = $derived(theme.value === "dark"
19 ? "text-white absolute top-0 z-[-2] h-screen w-screen bg-[#000000] bg-[radial-gradient(#ffffff33_1px,#00091d_1px)] bg-size-[20px_20px]"
20 : "text-black absolute inset-0 -z-10 h-full w-full bg-white bg-[radial-gradient(#e5e7eb_1px,transparent_1px)] bg-size-[16px_16px]"
21 );
22
23 function comingSoon() {
24 toast("Coming soon!", { icon: "🙈", position: "top-center" });
25 }
26
27 onMount(() => {
28 if (page.url.pathname === "/") {
29 goto(`/${pinned_list.value}`);
30 }
31 });
32</script>
33
34<div class={`${theme_style} font-apfel flex flex-col w-full h-full min-w-screen min-h-screen p-8 overflow-auto`}>
35 <section class="p-4 w-full h-full">
36 {@render children()}
37 </section>
38
39 <aside class="z-50 fixed inset-x-0 bottom-0 text-black! flex w-full h-fit items-end justify-between p-8 pointer-events-none">
40 <div class="flex flex-col justify-start gap-4 pointer-events-auto">
41 {#if is_menu_open}
42 <menu
43 transition:fade={{ duration: 150 }}
44 class={`${theme.value === "light" ? "border-black" : "border-[#00091d]"} w-fit border z-50 flex flex-col items-start gap-2 h-fit p-2 rounded-xl bg-white`}
45 >
46 <button
47 onclick={() => {
48 comingSoon();
49 is_menu_open = false;
50 }}
51 class="flex gap-2 text-start w-full h-full rounded-xl pl-2 pr-5 py-2 hover:bg-slate-500/10 transition-all duration-150 items-center"
52 >
53 <img src="/shooting-star-line.svg" alt="Item 1" class="w-8 h-8" />
54 Try a new list
55 </button>
56 <button
57 onclick={() => {
58 comingSoon();
59 is_menu_open = false;
60 }}
61 class="flex gap-2 text-start w-full h-full rounded-xl pl-2 pr-5 py-2 hover:bg-slate-500/10 transition-all duration-150 items-center"
62 >
63 <img src="/sparkles-line.svg" alt="Item 2" class="w-8 h-8" />
64 AI Suggestions
65 </button>
66 </menu>
67 {/if}
68
69 <nav class={`${theme.value === "light" ? "border-black" : "border-[#00091d]"} border z-50 flex self-center items-center gap-4 mx-auto w-fit h-fit p-2 rounded-xl bg-white`}>
70 <button
71 onclick={() => is_menu_open = !is_menu_open}
72 class="w-full h-fit hover:bg-slate-500/10 rounded-full"
73 >
74 <img src="/menu-line.svg" alt="Menu" class="w-12 h-12" />
75 </button>
76
77 <!-- TODO: change to <a href='/explore'> -->
78 <button
79 onclick={comingSoon}
80 class="items-center h-fit w-full hover:bg-slate-500/10 rounded-full"
81 >
82 <img src="/planet-rocket.svg" alt="Explore Page" class="w-12 h-12"/>
83 </button>
84
85 <!-- TODO: change to <a href='/login'> -->
86 <button
87 onclick={comingSoon}
88 class="items-center h-fit w-full hover:bg-slate-500/10 rounded-full"
89 >
90 <img src="/login-line.svg" alt="Login" class="w-12 h-12"/>
91 </button>
92 </nav>
93 </div>
94
95
96 <button
97 onclick={() => { theme.value = theme.value === "light" ? "dark" : "light" }}
98 class={`${theme.value === "light" ? "border-black" : "border-[#00091d]"} border w-fit h-fit p-2 bg-white rounded-xl pointer-events-auto`}
99 >
100 <img
101 src="/light-bulb.svg"
102 alt="Theme toggle button"
103 class="w-12 h-12 hover:bg-slate-500/10 rounded-full"
104 />
105 </button>
106 </aside>
107 <Toaster />
108</div>
109
110<style lang="postcss">
111 @reference "tailwindcss";
112</style>