summaryrefslogtreecommitdiffstats
path: root/src/ui/objects/Avatar.tsx
blob: 459af1296608f5c95f58d33db37ddef2dca2310e (plain) (blame)
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
import type { HTMLTag, Polymorphic } from "corvos/plugins/jsx.ts";

import { StatusIndicator } from "$/ui/objects/StatusIndicator.tsx";

export type Props<Tag extends HTMLTag> = Polymorphic<{
	"as"?: Tag;
	"src"?: string;
	"icon"?: JSX.Element;
	"children"?: JSX.Element;
	"class"?: string;
	"circle"?: boolean;
	"placeholder"?: boolean;
	"color"?: `hsl(${number}, ${number}%, ${number}%)`;
	"color2"?: `hsl(${number}, ${number}%, ${number}%)`;
	"color-angle"?: number | `${number}`;
	"size"?: "xs" | "sm" | "lg" | "xl" | "xxl" | "xxxl";
	"status"?: "accent" | "positive" | "negative" | "warning";
}>;

const hslRegex = /^hsl\(([\d.]+), ([\d.]+%), ([\d.]+%)\)$/;

export const Avatar = <T extends HTMLTag = "div">({
	children,
	as: Tag = "div" as T,
	src,
	icon,
	circle,
	placeholder,
	color,
	color2,
	"color-angle": colorAngle,
	size,
	status,
	class: cls,
	...props
}: Props<T>) => (
	<Tag
		class:list={[
			"o-avatar",
			{
				"o-avatar--circle": circle,
				"o-avatar--placeholder": placeholder,
				"o-avatar--colored": color && !color2,
				"o-avatar--colored-gradient": color && !!color2,
				[`o-avatar--${size}`]: !!size,
			},
			cls,
		]}
		style={{
			"--o-avatar--bg-angle": colorAngle,
			"--o-avatar--bg-color--h": color?.match(hslRegex)?.[1],
			"--o-avatar--bg-color--l": color?.match(hslRegex)?.[3],
			"--o-avatar--bg-color--s": color?.match(hslRegex)?.[2],
			"--o-avatar--bg-color-2--h": color2?.match(hslRegex)?.[1],
			"--o-avatar--bg-color-2--l": color2?.match(hslRegex)?.[3],
			"--o-avatar--bg-color-2--s": color2?.match(hslRegex)?.[2],
		}}
		{...props}
	>
		{status && <StatusIndicator class="o-avatar__status" status={status} />}
		{icon && <div class="o-avatar__icon u-ai-end u-jc-end">{icon}</div>}

		{src ? (
			<img alt="" class="o-avatar__content" src={src} />
		) : (
			<span class="o-avatar__content">{children}</span>
		)}
	</Tag>
);