summaryrefslogtreecommitdiffstats
path: root/src/ui/objects/Avatar.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/objects/Avatar.tsx')
-rw-r--r--src/ui/objects/Avatar.tsx69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/ui/objects/Avatar.tsx b/src/ui/objects/Avatar.tsx
new file mode 100644
index 0000000..459af12
--- /dev/null
+++ b/src/ui/objects/Avatar.tsx
@@ -0,0 +1,69 @@
1import type { HTMLTag, Polymorphic } from "corvos/plugins/jsx.ts";
2
3import { StatusIndicator } from "$/ui/objects/StatusIndicator.tsx";
4
5export type Props<Tag extends HTMLTag> = Polymorphic<{
6 "as"?: Tag;
7 "src"?: string;
8 "icon"?: JSX.Element;
9 "children"?: JSX.Element;
10 "class"?: string;
11 "circle"?: boolean;
12 "placeholder"?: boolean;
13 "color"?: `hsl(${number}, ${number}%, ${number}%)`;
14 "color2"?: `hsl(${number}, ${number}%, ${number}%)`;
15 "color-angle"?: number | `${number}`;
16 "size"?: "xs" | "sm" | "lg" | "xl" | "xxl" | "xxxl";
17 "status"?: "accent" | "positive" | "negative" | "warning";
18}>;
19
20const hslRegex = /^hsl\(([\d.]+), ([\d.]+%), ([\d.]+%)\)$/;
21
22export const Avatar = <T extends HTMLTag = "div">({
23 children,
24 as: Tag = "div" as T,
25 src,
26 icon,
27 circle,
28 placeholder,
29 color,
30 color2,
31 "color-angle": colorAngle,
32 size,
33 status,
34 class: cls,
35 ...props
36}: Props<T>) => (
37 <Tag
38 class:list={[
39 "o-avatar",
40 {
41 "o-avatar--circle": circle,
42 "o-avatar--placeholder": placeholder,
43 "o-avatar--colored": color && !color2,
44 "o-avatar--colored-gradient": color && !!color2,
45 [`o-avatar--${size}`]: !!size,
46 },
47 cls,
48 ]}
49 style={{
50 "--o-avatar--bg-angle": colorAngle,
51 "--o-avatar--bg-color--h": color?.match(hslRegex)?.[1],
52 "--o-avatar--bg-color--l": color?.match(hslRegex)?.[3],
53 "--o-avatar--bg-color--s": color?.match(hslRegex)?.[2],
54 "--o-avatar--bg-color-2--h": color2?.match(hslRegex)?.[1],
55 "--o-avatar--bg-color-2--l": color2?.match(hslRegex)?.[3],
56 "--o-avatar--bg-color-2--s": color2?.match(hslRegex)?.[2],
57 }}
58 {...props}
59 >
60 {status && <StatusIndicator class="o-avatar__status" status={status} />}
61 {icon && <div class="o-avatar__icon u-ai-end u-jc-end">{icon}</div>}
62
63 {src ? (
64 <img alt="" class="o-avatar__content" src={src} />
65 ) : (
66 <span class="o-avatar__content">{children}</span>
67 )}
68 </Tag>
69);