Monorepo for Tangled
0

Configure Feed

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

web/lib/components: add key card and add-key form components

Signed-off-by: oppiliappan <me@oppi.li>

author
oppiliappan
date (Jul 17, 2026, 4:28 PM +0100) commit 87e53b3f parent 35d264b1 change-id svsppsum
+110
+70
web/src/lib/components/settings/AddKeyForm.svelte
··· 1 + <script lang="ts"> 2 + import Button from "$lib/components/ui/Button.svelte"; 3 + import Spinner from "$lib/components/ui/Spinner.svelte"; 4 + import ErrorAlert from "$lib/components/ui/Error.svelte"; 5 + import Plus from "$icon/plus"; 6 + import X from "$icon/x"; 7 + 8 + interface Props { 9 + name?: string; 10 + key?: string; 11 + submitting?: boolean; 12 + error?: string | null; 13 + onSubmit: () => void; 14 + onCancel: () => void; 15 + } 16 + 17 + let { 18 + name = $bindable(""), 19 + key = $bindable(""), 20 + submitting = false, 21 + error = null, 22 + onSubmit, 23 + onCancel 24 + }: Props = $props(); 25 + 26 + const handleSubmit = (e: SubmitEvent) => { 27 + e.preventDefault(); 28 + onSubmit(); 29 + }; 30 + </script> 31 + 32 + <form onsubmit={handleSubmit} class="flex w-full flex-col gap-2"> 33 + <label for="key-name" class="font-medium text-foreground-default">Add SSH key</label> 34 + <p class="text-sm text-foreground-subtle"> 35 + SSH keys allow you to push to repositories in knots you're a member of. 36 + </p> 37 + <input 38 + id="key-name" 39 + type="text" 40 + placeholder="Key name" 41 + required 42 + bind:value={name} 43 + disabled={submitting} 44 + class="rounded border border-border-default bg-background-default px-2 py-2 text-sm text-foreground-default placeholder:text-foreground-placeholder focus:ring-1 focus:ring-border-strong focus:outline-none disabled:opacity-50" 45 + /> 46 + <textarea 47 + id="key-value" 48 + placeholder="ssh-ed25519 AAAAC3NzaC1..." 49 + required 50 + rows={3} 51 + spellcheck={false} 52 + bind:value={key} 53 + disabled={submitting} 54 + class="resize-y rounded border border-border-default bg-background-default px-2 py-2 font-mono text-sm text-foreground-default placeholder:text-foreground-placeholder focus:ring-1 focus:ring-border-strong focus:outline-none disabled:opacity-50" 55 + ></textarea> 56 + <div class="flex justify-end gap-2 pt-1"> 57 + <Button type="button" icon={X} onclick={onCancel} disabled={submitting}>Cancel</Button> 58 + <Button 59 + type="submit" 60 + variant="primary" 61 + icon={submitting ? Spinner : Plus} 62 + disabled={submitting} 63 + > 64 + Add 65 + </Button> 66 + </div> 67 + {#if error} 68 + <ErrorAlert label={error} /> 69 + {/if} 70 + </form>
+40
web/src/lib/components/settings/KeyCard.svelte
··· 1 + <script lang="ts"> 2 + import { relativeTime } from "$lib/format"; 3 + import Button from "$lib/components/ui/Button.svelte"; 4 + import Spinner from "$lib/components/ui/Spinner.svelte"; 5 + import KeyIcon from "$icon/key"; 6 + import Trash2 from "$icon/trash-2"; 7 + 8 + interface Props { 9 + name: string; 10 + fingerprint?: string; 11 + createdAt: string; 12 + deleting?: boolean; 13 + onDelete: () => void; 14 + } 15 + 16 + let { name, fingerprint, createdAt, deleting = false, onDelete }: Props = $props(); 17 + </script> 18 + 19 + <div 20 + class="flex items-center justify-between gap-2 bg-background-default" 21 + > 22 + <div class="flex min-w-0 flex-col gap-1"> 23 + <div class="flex items-center gap-2"> 24 + <KeyIcon class="size-4 shrink-0 text-foreground-muted" aria-hidden="true" /> 25 + <span class="font-bold text-foreground-default">{name}</span> 26 + </div> 27 + {#if fingerprint} 28 + <span class="truncate font-mono text-sm text-foreground-subtle">{fingerprint}</span> 29 + {/if} 30 + <span class="text-sm text-foreground-subtle">added {relativeTime(createdAt)}</span> 31 + </div> 32 + <Button 33 + variant="danger" 34 + icon={deleting ? Spinner : Trash2} 35 + disabled={deleting} 36 + onclick={onDelete} 37 + > 38 + Delete 39 + </Button> 40 + </div>