This repository has no description
1<script module lang="ts">
2 import { tv, type VariantProps } from "tailwind-variants";
3
4 export const avatarPicker = tv({
5 slots: {
6 label:
7 "flex size-40 cursor-pointer flex-col items-center justify-center gap-1 overflow-hidden rounded-full border border-border-default text-foreground-subtle transition-colors hover:bg-background-subtle",
8 image: "size-full rounded-full object-cover",
9 placeholder: "flex flex-col items-center justify-center gap-1"
10 }
11 });
12
13 export type AvatarPickerVariants = VariantProps<typeof avatarPicker>;
14</script>
15
16<script lang="ts">
17 import Camera from "$icon/camera";
18 import Field from "$lib/components/ui/Field.svelte";
19 import Input from "$lib/components/ui/Input.svelte";
20 import StepHeader from "./StepHeader.svelte";
21 import { draft } from "./draft.svelte";
22
23 const slot = avatarPicker();
24
25 // no upload endpoint wired up: the preview is a local object url, which is all
26 // the appview shows before its hx-post to /profile/avatar comes back
27 const pick = (event: Event) => {
28 const file = (event.currentTarget as HTMLInputElement).files?.[0];
29 if (!file) return;
30 if (draft.picture) URL.revokeObjectURL(draft.picture);
31 draft.picture = URL.createObjectURL(file);
32 };
33</script>
34
35<div class="flex flex-col gap-6">
36 <StepHeader title="Welcome!" subtitle="Let's get your profile ready. All fields are optional." />
37
38 <div class="flex flex-col gap-6 md:flex-row">
39 <div class="flex shrink-0 justify-center md:block">
40 <label class={slot.label()}>
41 {#if draft.picture}
42 <img src={draft.picture} alt="Your new avatar" class={slot.image()} />
43 {:else}
44 <span class={slot.placeholder()}>
45 <Camera class="size-6" aria-hidden="true" />
46 <span class="typography-paragraph-small">Upload picture</span>
47 </span>
48 {/if}
49 <input type="file" accept="image/png,image/jpeg" class="hidden" onchange={pick} />
50 </label>
51 </div>
52
53 <div class="flex min-w-0 flex-1 flex-col gap-4">
54 <Field label="Bio" labelCase="normal">
55 {#snippet children({ id })}
56 <Input {id} placeholder="Tell us about yourself" bind:value={draft.description} />
57 {/snippet}
58 </Field>
59
60 <Field label="Pronouns" labelCase="normal">
61 {#snippet children({ id })}
62 <Input {id} placeholder="they/them" bind:value={draft.pronouns} />
63 {/snippet}
64 </Field>
65
66 <Field label="Website" labelCase="normal">
67 {#snippet children({ id })}
68 <Input {id} placeholder="example.com" bind:value={draft.website} />
69 {/snippet}
70 </Field>
71 </div>
72 </div>
73</div>