-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Expand file tree
/
Copy pathAvatar.astro
More file actions
77 lines (72 loc) · 1.79 KB
/
Avatar.astro
File metadata and controls
77 lines (72 loc) · 1.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
---
/**
* Avatar Primitive Component
*
* A rounded avatar image (or stacked images for multiple authors)
* with a name and optional caption displayed to the right.
*
* @example — Single author
* <Avatar
* authors={[{ src: "/images/author.jpg", name: "John Doe" }]}
* caption="Jun 05, 2025"
* />
*
* @example — Multiple authors
* <Avatar
* authors={[
* { src: "/images/a.jpg", name: "Alex Pit" },
* { src: "/images/b.jpg", name: "Tom Cruise" },
* ]}
* caption="Mar 04, 2026"
* />
*
* @example — Small size
* <Avatar
* authors={[{ src: "/images/author.jpg", name: "Jane Smith" }]}
* caption="Mar 04, 2026"
* size="sm"
* />
*/
import './Avatar.css';
import type { HTMLAttributes } from 'astro/types';
import { Image } from 'astro:assets';
import { BodyMd, BodySm, Flex } from '@components/primitives';
interface Author {
src: string;
alt?: string;
name: string;
}
interface Props extends HTMLAttributes<'div'> {
authors: Author[];
caption?: string;
size?: 'sm' | 'md';
}
const { authors, caption, size = 'md', class: className, ...rest } = Astro.props;
const displayName = authors?.map((a) => a.name).join(', ') ?? '';
const imgSize = size === 'sm' ? 24 : 32;
---
<Flex align="center" gap="2" class:list={[`avatar--${size}`, className]} {...rest}>
<div class="avatar__images">
{
authors?.map((a) => (
<Image
class="avatar__image"
src={a.src}
alt={a.alt ?? a.name}
width={imgSize}
height={imgSize}
/>
))
}
</div>
<div class="avatar__content">
<BodyMd as="span" weight="medium" vMargin={false}>{displayName}</BodyMd>
{
caption && (
<BodySm as="span" color="secondary" vMargin={false}>
{caption}
</BodySm>
)
}
</div>
</Flex>