This repository has no description
0

Configure Feed

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

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