Monorepo for Tangled tangled.org
3

Configure Feed

Select the types of activity you want to include in your feed.

core / web / src / routes / login / +page.svelte
3.4 kB 110 lines
1<script lang="ts"> 2 import { browser } from "$app/environment"; 3 import { resolve } from "$app/paths"; 4 import { page } from "$app/state"; 5 import { getAuth } from "$lib/auth.svelte"; 6 import Button from "$lib/components/ui/Button.svelte"; 7 import CircleAlert from "$icon/circle-alert"; 8 import { onMount } from "svelte"; 9 import { SvelteURL } from "svelte/reactivity"; 10 11 const appPath = (path: string) => resolve(path as "/"); 12 const auth = getAuth(); 13 const returnTo = $derived(page.url.searchParams.get("return_url") ?? "/"); 14 15 let identifier = $state(page.url.searchParams.get("identifier") ?? ""); 16 let isSubmitting = $state(false); 17 18 onMount(() => { 19 if (browser && location.hostname === "localhost") { 20 const url = new SvelteURL(location.href); 21 url.hostname = "127.0.0.1"; 22 location.replace(url); 23 } 24 }); 25 26 const submit = async (event: SubmitEvent) => { 27 event.preventDefault(); 28 isSubmitting = true; 29 try { 30 await auth.signIn(identifier, returnTo); 31 } finally { 32 isSubmitting = false; 33 } 34 }; 35</script> 36 37<svelte:head> 38 <title>Login &middot; Tangled</title> 39</svelte:head> 40 41<section class="w-full max-w-md"> 42 <div class="mb-4 flex flex-col items-center"> 43 <a href={appPath("/")} class="flex items-center gap-2 no-underline hover:no-underline"> 44 <img src="/logos/logotype.svg" alt="tangled" class="h-24 w-48 dark:invert" /> 45 </a> 46 <p class="text-center text-xl text-foreground-default italic">tightly-knit social coding.</p> 47 </div> 48 49 <form class="mt-4" onsubmit={submit}> 50 <div class="flex flex-col"> 51 <label for="identifier" class="py-2 text-sm text-foreground-default">Handle</label> 52 <input 53 id="identifier" 54 bind:value={identifier} 55 disabled={isSubmitting} 56 type="text" 57 autocomplete="username" 58 autocapitalize="none" 59 spellcheck="false" 60 inputmode="url" 61 required 62 placeholder="akshay.tngl.sh" 63 class="w-full rounded border border-border-default bg-background-default p-3 text-lg text-foreground-default placeholder:text-foreground-placeholder focus:ring-1 focus:ring-border-strong focus:outline-none md:text-base" 64 /> 65 <p class="mt-1 text-sm text-foreground-subtle"> 66 Use your <span class="text-foreground-default">AT Protocol</span> handle to log in. If 67 you're unsure, this is likely your Tangled 68 <code class="rounded bg-background-inset px-1 font-mono text-xs text-foreground-default" 69 >(.tngl.sh)</code 70 > 71 or Bluesky 72 <code class="rounded bg-background-inset px-1 font-mono text-xs text-foreground-default" 73 >(.bsky.social)</code 74 > 75 account. 76 </p> 77 </div> 78 79 <Button 80 type="submit" 81 size="sm" 82 disabled={isSubmitting} 83 loading={isSubmitting} 84 spinnerClass="size-4" 85 aria-label={isSubmitting ? "Logging in" : undefined} 86 class="my-2 mt-6 w-full text-base disabled:opacity-100" 87 > 88 Login 89 </Button> 90 </form> 91 92 <p class="text-sm text-foreground-subtle"> 93 Don't have an account? <a href={appPath("/signup")} class="text-foreground-default underline" 94 >Create an account</a 95 > 96 on Tangled now! 97 </p> 98 99 {#if auth.error} 100 <div 101 class="my-2 flex gap-2 rounded border border-border-danger bg-background-danger-subtle px-3 py-2 text-foreground-danger drop-shadow-sm" 102 > 103 <span class="py-1" aria-hidden="true"><CircleAlert class="size-4" /></span> 104 <div> 105 <h5 class="font-medium">Login error</h5> 106 <p class="text-sm">{auth.error} Please try again.</p> 107 </div> 108 </div> 109 {/if} 110</section>