rainbow-fe/src/lib/components/AccountProfile.svelte

123 lines
2.3 KiB
Svelte

<script lang="ts">
import { onMount } from 'svelte';
import type { MastodonAccount } from '$lib/mastoapi/account';
export let account: MastodonAccount;
let fieldsNode: HTMLElement;
onMount(() => {
for (const a of Array.from(fieldsNode.querySelectorAll('dd a'))) {
const href = a.getAttribute('href');
if (href == null) continue;
if (new URL(href, window.location.href).origin != window.location.origin) {
a.setAttribute('title', href);
a.setAttribute('target', '_blank');
a.setAttribute('rel', 'nofollow noopener external');
}
}
});
</script>
<article class="account-profile">
<header>
<img class="avatar" alt={account.acct} src={account.avatar} />
<div>
<h1>{account.display_name}</h1>
<a class="link-muted" href={account.url} target="_blank" rel="nofollow noopener external">
@{account.fqn}
</a>
</div>
</header>
<div class="about">
<div class="fields" bind:this={fieldsNode}>
{#each account.fields as field}
<dl>
<dt>{field.name}</dt>
<dd>{@html field.value}</dd>
</dl>
{/each}
</div>
<div class="bio">
{@html account.note}
</div>
</div>
</article>
<style>
.account-profile {
background: var(--col-bg-1);
padding: 1em;
}
.account-profile header {
display: flex;
flex-direction: row;
margin-bottom: 1em;
}
.account-profile header .avatar {
width: 5em;
height: 5em;
border-radius: 6px;
margin-inline-end: 1em;
}
.account-profile header > div {
width: 100%;
}
.about {
display: flex;
flex-direction: column;
}
.about > * {
border: 1px solid var(--col-bg-2);
border-collapse: collapse;
padding: 1em;
}
.bio {
border-block-start: none;
}
.fields dl {
display: flex;
margin: 0;
}
.fields dt {
background: var(--col-bg-2);
font-weight: 500;
max-width: 12ch;
min-width: 12ch;
}
.fields dd {
flex: 1 1 auto;
}
.fields dt,
.fields dd {
padding: 0.8em;
text-overflow: ellipsis;
overflow: hidden;
margin: 0;
max-height: 1em;
white-space: nowrap;
}
:global(.bio > p:first-child) {
margin-top: 0;
}
:global(.bio > p:last-child) {
margin-bottom: 0;
}
</style>