atagen

malice

public
Star0
Watch0
0380cd8c765cdd7735d5c259c26abdeef712e742
2
ssh://brewery@pls.lobotomise.me:33/atagen/malice.git
web/src/lib/MxcAvatar.svelteSvelte56 lines1.3 KB
1
<script lang="ts">
2
  import { mediaUrl } from './api';
3
  import { initialsOf } from './format';
4
5
  export let mxc: string | null;
6
  export let label: string;
7
  export let size = 34;
8
  /** 'circle' for people, 'rounded' for rooms/spaces */
9
  export let shape: 'circle' | 'rounded' = 'circle';
10
11
  $: src = mediaUrl(mxc);
12
13
  let failed = false;
14
  $: if (mxc) failed = false;
15
  $: px = `${size}px`;
16
  $: fontPx = `${Math.max(10, Math.round(size * 0.36))}px`;
17
</script>
18
19
{#if src && !failed}
20
  <img
21
    {src}
22
    alt=""
23
    aria-hidden="true"
24
    width={size}
25
    height={size}
26
    loading="lazy"
27
    class="mxc-avatar"
28
    class:circle={shape === 'circle'}
29
    style={`width:${px};height:${px};`}
30
    on:error={() => (failed = true)}
31
  />
32
{:else}
33
  <span class="mxc-fallback" class:circle={shape === 'circle'} aria-hidden="true" style={`width:${px};height:${px};font-size:${fontPx};`}>
34
    {initialsOf(label || '#')}
35
  </span>
36
{/if}
37
38
<style>
39
  .mxc-avatar {
40
    flex: none;
41
    object-fit: cover;
42
    border-radius: 8px;
43
    background: var(--bg-soft);
44
  }
45
  .mxc-avatar.circle { border-radius: 50%; }
46
  .mxc-fallback {
47
    flex: none;
48
    display: inline-grid;
49
    place-items: center;
50
    border-radius: 8px;
51
    background: var(--panel-2);
52
    color: var(--text);
53
    font-weight: 700;
54
  }
55
  .mxc-fallback.circle { border-radius: 50%; }
56
</style>