feat: Add verified badge to team member card (#216)

Co-authored-by: Kendell R <KTibow@users.noreply.github.com>
Co-authored-by: Ushie <ushiekane@gmail.com>
This commit is contained in:
oSumAtrIX 2024-09-08 22:31:57 +02:00 committed by GitHub
parent 7c066ac0b5
commit 486e9ef62e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 158 additions and 13 deletions

View File

@ -32,6 +32,7 @@
"svelte": "4.2.18", "svelte": "4.2.18",
"svelte-check": "3.8.4", "svelte-check": "3.8.4",
"svelte-meta-tags": "3.1.2", "svelte-meta-tags": "3.1.2",
"svooltip": "^0.8.2",
"tslib": "2.6.3", "tslib": "2.6.3",
"typescript": "5.5.3", "typescript": "5.5.3",
"vite": "5.3.3", "vite": "5.3.3",

33
pnpm-lock.yaml generated
View File

@ -81,6 +81,9 @@ importers:
svelte-meta-tags: svelte-meta-tags:
specifier: 3.1.2 specifier: 3.1.2
version: 3.1.2(svelte@4.2.18)(typescript@5.5.3) version: 3.1.2(svelte@4.2.18)(typescript@5.5.3)
svooltip:
specifier: ^0.8.2
version: 0.8.2(svelte@4.2.18)
tslib: tslib:
specifier: 2.6.3 specifier: 2.6.3
version: 2.6.3 version: 2.6.3
@ -259,6 +262,15 @@ packages:
resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
'@floating-ui/core@1.6.7':
resolution: {integrity: sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g==}
'@floating-ui/dom@1.6.10':
resolution: {integrity: sha512-fskgCFv8J8OamCmyun8MfjB1Olfn+uZKjOKZ0vhYF3gRmEUXcGOjxWL8bBr7i4kIuPZ2KD2S3EUIOxnjC8kl2A==}
'@floating-ui/utils@0.2.7':
resolution: {integrity: sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==}
'@humanwhocodes/config-array@0.11.14': '@humanwhocodes/config-array@0.11.14':
resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==}
engines: {node: '>=10.10.0'} engines: {node: '>=10.10.0'}
@ -1376,6 +1388,11 @@ packages:
resolution: {integrity: sha512-d0FdzYIiAePqRJEb90WlJDkjUEx42xhivxN8muUBmfZnP+tzUgz12DJ2hRJi8sIHCME7jeK1PTMgKPSfTd8JrA==} resolution: {integrity: sha512-d0FdzYIiAePqRJEb90WlJDkjUEx42xhivxN8muUBmfZnP+tzUgz12DJ2hRJi8sIHCME7jeK1PTMgKPSfTd8JrA==}
engines: {node: '>=16'} engines: {node: '>=16'}
svooltip@0.8.2:
resolution: {integrity: sha512-tNuWxAf8A6li0aJNUAuyWrUtNpT7SAii4nuiB3t79K6bngRF3MNQ6jgJdeWN0Y1ZaplJA308MPlIbIF9SioiKw==}
peerDependencies:
svelte: ^4.0.0
text-table@0.2.0: text-table@0.2.0:
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
@ -1586,6 +1603,17 @@ snapshots:
'@eslint/js@8.57.0': {} '@eslint/js@8.57.0': {}
'@floating-ui/core@1.6.7':
dependencies:
'@floating-ui/utils': 0.2.7
'@floating-ui/dom@1.6.10':
dependencies:
'@floating-ui/core': 1.6.7
'@floating-ui/utils': 0.2.7
'@floating-ui/utils@0.2.7': {}
'@humanwhocodes/config-array@0.11.14': '@humanwhocodes/config-array@0.11.14':
dependencies: dependencies:
'@humanwhocodes/object-schema': 2.0.3 '@humanwhocodes/object-schema': 2.0.3
@ -2695,6 +2723,11 @@ snapshots:
magic-string: 0.30.11 magic-string: 0.30.11
periscopic: 3.1.0 periscopic: 3.1.0
svooltip@0.8.2(svelte@4.2.18):
dependencies:
'@floating-ui/dom': 1.6.10
svelte: 4.2.18
text-table@0.2.0: {} text-table@0.2.0: {}
tiny-glob@0.2.9: tiny-glob@0.2.9:

View File

@ -0,0 +1,29 @@
<script lang="ts">
import { tooltip } from 'svooltip';
import '../styles/ToolTip.scss';
export let content: string;
export let html: boolean = false;
</script>
<div
use:tooltip={{
content: content,
html: html
}}
>
<slot />
</div>
<style>
:root {
--svooltip-bg: var(--surface-three);
--svooltip-text: var(--text-four);
--svooltip-padding: 0.75rem 1rem;
--svooltip-weight: bold;
--svooltip-text-size: 16px;
--svooltip-shadow: var(--drop-shadow-one);
--svooltip-arrow-size: 0;
--svooltip-roundness: 12px;
}
</style>

View File

@ -0,0 +1,12 @@
@use 'svooltip/styles.scss' as SvoolTip;
.svooltip a {
text-decoration: none;
color: var(--text-four);
pointer-events: all;
&:hover {
text-decoration: underline var(--secondary);
color: var(--secondary);
}
}

View File

@ -49,6 +49,12 @@ export interface TeamMember {
avatar_url: string; avatar_url: string;
url: string; url: string;
bio?: string; bio?: string;
gpg_key: GpgKey;
}
expose interface GpgKey {
id: string;
url: string;
} }
export interface CryptoWallet { export interface CryptoWallet {

View File

@ -3,35 +3,69 @@
import { quintOut } from 'svelte/easing'; import { quintOut } from 'svelte/easing';
import type { TeamMember } from '$lib/types'; import type { TeamMember } from '$lib/types';
import ToolTip from '$lib/components/ToolTip.svelte';
import Svg from '$lib/components/Svg.svelte';
export let member: TeamMember; export let member: TeamMember;
export let i: number; export let i: number;
const transitionOptions = {
y: 10,
easing: quintOut,
duration: 750,
delay: 50 * i
};
const verifiedIconPath =
'm9.585.52.929.68c.153.112.331.186.518.215l1.138.175a2.678 2.678 0 0 1 2.24 2.24l.174 1.139c.029.187.103.365.215.518l.68.928a2.677 2.677 0 0 1 0 3.17l-.68.928a1.174 1.174 0 0 0-.215.518l-.175 1.138a2.678 2.678 0 0 1-2.241 2.241l-1.138.175a1.17 1.17 0 0 0-.518.215l-.928.68a2.677 2.677 0 0 1-3.17 0l-.928-.68a1.174 1.174 0 0 0-.518-.215L3.83 14.41a2.678 2.678 0 0 1-2.24-2.24l-.175-1.138a1.17 1.17 0 0 0-.215-.518l-.68-.928a2.677 2.677 0 0 1 0-3.17l.68-.928c.112-.153.186-.331.215-.518l.175-1.14a2.678 2.678 0 0 1 2.24-2.24l1.139-.175c.187-.029.365-.103.518-.215l.928-.68a2.677 2.677 0 0 1 3.17 0ZM7.303 1.728l-.927.68a2.67 2.67 0 0 1-1.18.489l-1.137.174a1.179 1.179 0 0 0-.987.987l-.174 1.136a2.677 2.677 0 0 1-.489 1.18l-.68.928a1.18 1.18 0 0 0 0 1.394l.68.927c.256.348.424.753.489 1.18l.174 1.137c.078.509.478.909.987.987l1.136.174a2.67 2.67 0 0 1 1.18.489l.928.68c.414.305.979.305 1.394 0l.927-.68a2.67 2.67 0 0 1 1.18-.489l1.137-.174a1.18 1.18 0 0 0 .987-.987l.174-1.136a2.67 2.67 0 0 1 .489-1.18l.68-.928a1.176 1.176 0 0 0 0-1.394l-.68-.927a2.686 2.686 0 0 1-.489-1.18l-.174-1.137a1.179 1.179 0 0 0-.987-.987l-1.136-.174a2.677 2.677 0 0 1-1.18-.489l-.928-.68a1.176 1.176 0 0 0-1.394 0ZM11.28 6.78l-3.75 3.75a.75.75 0 0 1-1.06 0L4.72 8.78a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L7 8.94l3.22-3.22a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z';
</script> </script>
<a <div class="member">
class="member" <a href={member.url} rel="noreferrer" target="_blank" in:fly|global={transitionOptions}>
href={member.url}
rel="noreferrer"
target="_blank"
in:fly|global={{ y: 10, easing: quintOut, duration: 750, delay: 50 * i }}
>
<img src={member.avatar_url} alt="{member.name}'s profile picture." /> <img src={member.avatar_url} alt="{member.name}'s profile picture." />
</a>
<div class="member-text"> <div class="member-text">
<div class="member-title">
<a href={member.url} rel="noreferrer" target="_blank" in:fly|global={transitionOptions}>
<h4>{member.name}</h4> <h4>{member.name}</h4>
</a>
<div class="verified-badge">
<ToolTip
content="<p><b>{member.name}</b> is verified with this GPG Key ID:</p> <a class='gpg-url' href={member
.gpg_key.url} rel='noreferrer' target='_blank'>{member.gpg_key.id}</a>"
html={true}
>
<div class="desktop-verified">
<a href={member.gpg_key.url} rel="noreferrer" target="_blank">
<Svg svgHeight={16} viewBoxHeight={16}>
<path d={verifiedIconPath} />
</Svg>
</a>
</div>
<div class="mobile-verified">
<Svg svgHeight={16} viewBoxHeight={16}>
<path d={verifiedIconPath} />
</Svg>
<h5>Verified</h5>
</div>
</ToolTip>
</div>
</div>
{#if member.bio} {#if member.bio}
<h6>{member.bio}</h6> <h6>{member.bio}</h6>
{/if} {/if}
</div> </div>
</a> </div>
<style lang="scss"> <style lang="scss">
a {
text-decoration: none;
}
.member { .member {
width: 100%; width: 100%;
color: var(--text-one); color: var(--text-one);
border: 1px solid var(--border); border: 1px solid var(--border);
text-decoration: none;
cursor: pointer;
padding: 1rem; padding: 1rem;
border-radius: 12px; border-radius: 12px;
display: flex; display: flex;
@ -47,6 +81,36 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
word-break: break-word; word-break: break-word;
.member-title {
display: flex;
align-items: center;
gap: 0.5rem;
.verified-badge {
display: flex;
align-items: center;
fill: var(--secondary);
line-height: 16px;
height: 16px;
.mobile-verified {
display: none;
}
@media screen and (width <= 768px) {
.desktop-verified {
display: none;
}
.mobile-verified {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 0.25rem;
}
}
}
}
} }
img { img {