@rovula/ui 0.0.13 → 0.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/dist/cjs/bundle.css +227 -16
  2. package/dist/cjs/bundle.js +3 -3
  3. package/dist/cjs/bundle.js.map +1 -1
  4. package/dist/cjs/types/components/ActionButton/ActionButton.d.ts +20 -0
  5. package/dist/cjs/types/components/ActionButton/ActionButton.stories.d.ts +311 -0
  6. package/dist/cjs/types/components/ActionButton/ActionButton.styles.d.ts +6 -0
  7. package/dist/cjs/types/components/Avatar/Avatar.d.ts +32 -0
  8. package/dist/cjs/types/components/Avatar/Avatar.stories.d.ts +64 -0
  9. package/dist/cjs/types/components/Avatar/Avatar.styles.d.ts +4 -0
  10. package/dist/cjs/types/components/Avatar/AvatarBase.d.ts +6 -0
  11. package/dist/cjs/types/components/Avatar/AvatarGroup.d.ts +11 -0
  12. package/dist/cjs/types/components/Avatar/AvatarGroup.stories.d.ts +31 -0
  13. package/dist/cjs/types/components/Input/Input.d.ts +21 -4
  14. package/dist/cjs/types/components/Input/Input.stories.d.ts +340 -22
  15. package/dist/cjs/types/components/Input/Input.styles.d.ts +9 -0
  16. package/dist/cjs/types/components/Label/Label.d.ts +6 -1
  17. package/dist/cjs/types/components/Label/Label.stories.d.ts +10 -1
  18. package/dist/cjs/types/components/Label/Label.styles.d.ts +6 -0
  19. package/dist/cjs/types/components/Navbar/Navbar.d.ts +12 -0
  20. package/dist/cjs/types/components/Navbar/Navbar.stories.d.ts +35 -0
  21. package/dist/cjs/types/components/Search/Search.d.ts +2 -0
  22. package/dist/cjs/types/components/Search/Search.stories.d.ts +21 -0
  23. package/dist/cjs/types/components/ThemeToggle.d.ts +2 -0
  24. package/dist/components/ActionButton/ActionButton.js +38 -0
  25. package/dist/components/ActionButton/ActionButton.stories.js +45 -0
  26. package/dist/components/ActionButton/ActionButton.styles.js +71 -0
  27. package/dist/components/Avatar/Avatar.js +22 -0
  28. package/dist/components/Avatar/Avatar.stories.js +47 -0
  29. package/dist/components/Avatar/Avatar.styles.js +23 -0
  30. package/dist/components/Avatar/AvatarBase.js +43 -0
  31. package/dist/components/Avatar/AvatarGroup.js +21 -0
  32. package/dist/components/Avatar/AvatarGroup.stories.js +47 -0
  33. package/dist/components/Button/Button.styles.js +6 -6
  34. package/dist/components/Input/Input.js +5 -4
  35. package/dist/components/Input/Input.stories.js +2 -4
  36. package/dist/components/Input/Input.styles.js +45 -0
  37. package/dist/components/Label/Label.js +7 -3
  38. package/dist/components/Label/Label.styles.js +57 -0
  39. package/dist/components/Navbar/Navbar.js +9 -0
  40. package/dist/components/Navbar/Navbar.stories.js +41 -0
  41. package/dist/components/Search/Search.js +19 -0
  42. package/dist/components/Search/Search.stories.js +36 -0
  43. package/dist/components/Text/Text.js +2 -1
  44. package/dist/components/ThemeToggle.js +17 -0
  45. package/dist/esm/bundle.css +227 -16
  46. package/dist/esm/bundle.js +3 -3
  47. package/dist/esm/bundle.js.map +1 -1
  48. package/dist/esm/types/components/ActionButton/ActionButton.d.ts +20 -0
  49. package/dist/esm/types/components/ActionButton/ActionButton.stories.d.ts +311 -0
  50. package/dist/esm/types/components/ActionButton/ActionButton.styles.d.ts +6 -0
  51. package/dist/esm/types/components/Avatar/Avatar.d.ts +32 -0
  52. package/dist/esm/types/components/Avatar/Avatar.stories.d.ts +64 -0
  53. package/dist/esm/types/components/Avatar/Avatar.styles.d.ts +4 -0
  54. package/dist/esm/types/components/Avatar/AvatarBase.d.ts +6 -0
  55. package/dist/esm/types/components/Avatar/AvatarGroup.d.ts +11 -0
  56. package/dist/esm/types/components/Avatar/AvatarGroup.stories.d.ts +31 -0
  57. package/dist/esm/types/components/Input/Input.d.ts +21 -4
  58. package/dist/esm/types/components/Input/Input.stories.d.ts +340 -22
  59. package/dist/esm/types/components/Input/Input.styles.d.ts +9 -0
  60. package/dist/esm/types/components/Label/Label.d.ts +6 -1
  61. package/dist/esm/types/components/Label/Label.stories.d.ts +10 -1
  62. package/dist/esm/types/components/Label/Label.styles.d.ts +6 -0
  63. package/dist/esm/types/components/Navbar/Navbar.d.ts +12 -0
  64. package/dist/esm/types/components/Navbar/Navbar.stories.d.ts +35 -0
  65. package/dist/esm/types/components/Search/Search.d.ts +2 -0
  66. package/dist/esm/types/components/Search/Search.stories.d.ts +21 -0
  67. package/dist/esm/types/components/ThemeToggle.d.ts +2 -0
  68. package/dist/index.d.ts +22 -10
  69. package/dist/src/theme/global.css +290 -21
  70. package/dist/theme/global.css +11 -0
  71. package/dist/theme/presets/colors.js +28 -0
  72. package/package.json +2 -1
  73. package/src/components/ActionButton/ActionButton.stories.tsx +176 -0
  74. package/src/components/ActionButton/ActionButton.styles.ts +79 -0
  75. package/src/components/ActionButton/ActionButton.tsx +42 -0
  76. package/src/components/Avatar/Avatar.stories.tsx +107 -0
  77. package/src/components/Avatar/Avatar.styles.ts +28 -0
  78. package/src/components/Avatar/Avatar.tsx +88 -0
  79. package/src/components/Avatar/AvatarBase.tsx +50 -0
  80. package/src/components/Avatar/AvatarGroup.stories.tsx +77 -0
  81. package/src/components/Avatar/AvatarGroup.tsx +55 -0
  82. package/src/components/Button/Button.styles.ts +6 -6
  83. package/src/components/Input/Input.stories.tsx +8 -6
  84. package/src/components/Input/Input.styles.tsx +51 -0
  85. package/src/components/Input/Input.tsx +30 -6
  86. package/src/components/Label/Label.styles.ts +61 -0
  87. package/src/components/Label/Label.tsx +13 -7
  88. package/src/components/Navbar/Navbar.stories.tsx +86 -0
  89. package/src/components/Navbar/Navbar.tsx +56 -0
  90. package/src/components/Search/Search.stories.tsx +44 -0
  91. package/src/components/Search/Search.tsx +25 -0
  92. package/src/components/Text/Text.tsx +2 -1
  93. package/src/components/ThemeToggle.tsx +19 -0
  94. package/src/theme/global.css +11 -0
  95. package/src/theme/presets/colors.js +28 -0
@@ -0,0 +1,176 @@
1
+ import React from "react";
2
+ import type { Meta, StoryObj } from "@storybook/react";
3
+
4
+ import ActionButton from "./ActionButton";
5
+ import { ArrowsUpDownIcon } from "@heroicons/react/16/solid";
6
+
7
+ const meta = {
8
+ title: "Components/ActionButton",
9
+ component: ActionButton,
10
+ tags: ["autodocs"],
11
+ parameters: {
12
+ layout: "fullscreen",
13
+ },
14
+ decorators: [
15
+ (Story) => (
16
+ <div className="p-5">
17
+ <Story />
18
+ </div>
19
+ ),
20
+ ],
21
+ } satisfies Meta<typeof ActionButton>;
22
+
23
+ export default meta;
24
+
25
+ export const Default = {
26
+ args: {
27
+ variant: "solid",
28
+ size: "lg",
29
+ },
30
+ render: (args) => {
31
+ console.log("args ", args);
32
+ const props: typeof args = {
33
+ ...args,
34
+ };
35
+ return (
36
+ <div className="flex flex-row justify-between">
37
+ <ActionButton {...props}>
38
+ <ArrowsUpDownIcon />
39
+ </ActionButton>
40
+ </div>
41
+ );
42
+ },
43
+ } satisfies StoryObj;
44
+
45
+ export const Preview = {
46
+ args: {},
47
+ render: (args) => {
48
+ console.log("args ", args);
49
+ const props: typeof args = {
50
+ ...args,
51
+ };
52
+ return (
53
+ <div className="flex flex-col gap-2 w-full bg-black p-20">
54
+ <div className="flex flex-row justify-between items-center">
55
+ <h6 className="w-[20px] text-white">Default:</h6>
56
+ <div className="flex flex-row gap-2 ">
57
+ <ActionButton variant="solid" size="lg">
58
+ <ArrowsUpDownIcon />
59
+ </ActionButton>
60
+ <ActionButton variant="solid" size="md">
61
+ <ArrowsUpDownIcon />
62
+ </ActionButton>
63
+ <ActionButton variant="solid" size="sm">
64
+ <ArrowsUpDownIcon />
65
+ </ActionButton>
66
+ </div>
67
+ <div className="flex flex-row gap-2">
68
+ <ActionButton variant="outline" size="lg">
69
+ <ArrowsUpDownIcon />
70
+ </ActionButton>
71
+ <ActionButton variant="outline" size="md">
72
+ <ArrowsUpDownIcon />
73
+ </ActionButton>
74
+ <ActionButton variant="outline" size="sm">
75
+ <ArrowsUpDownIcon />
76
+ </ActionButton>
77
+ </div>
78
+ <div className="flex flex-row gap-2">
79
+ <ActionButton variant="icon" size="lg">
80
+ <ArrowsUpDownIcon />
81
+ </ActionButton>
82
+ <ActionButton variant="icon" size="md">
83
+ <ArrowsUpDownIcon />
84
+ </ActionButton>
85
+ <ActionButton variant="icon" size="sm">
86
+ <ArrowsUpDownIcon />
87
+ </ActionButton>
88
+ <ActionButton variant="icon" size="xs">
89
+ <ArrowsUpDownIcon />
90
+ </ActionButton>
91
+ </div>
92
+ </div>
93
+
94
+ <div className="flex flex-row justify-between">
95
+ <h6 className="w-[20px] text-white">Active:</h6>
96
+ <div className="flex flex-row gap-2">
97
+ <ActionButton variant="solid" size="lg" active>
98
+ <ArrowsUpDownIcon />
99
+ </ActionButton>
100
+ <ActionButton variant="solid" size="md" active>
101
+ <ArrowsUpDownIcon />
102
+ </ActionButton>
103
+ <ActionButton variant="solid" size="sm" active>
104
+ <ArrowsUpDownIcon />
105
+ </ActionButton>
106
+ </div>
107
+ <div className="flex flex-row gap-2">
108
+ <ActionButton variant="outline" size="lg" active>
109
+ <ArrowsUpDownIcon />
110
+ </ActionButton>
111
+ <ActionButton variant="outline" size="md" active>
112
+ <ArrowsUpDownIcon />
113
+ </ActionButton>
114
+ <ActionButton variant="outline" size="sm" active>
115
+ <ArrowsUpDownIcon />
116
+ </ActionButton>
117
+ </div>
118
+ <div className="flex flex-row gap-2">
119
+ <ActionButton variant="icon" size="lg" active>
120
+ <ArrowsUpDownIcon />
121
+ </ActionButton>
122
+ <ActionButton variant="icon" size="md" active>
123
+ <ArrowsUpDownIcon />
124
+ </ActionButton>
125
+ <ActionButton variant="icon" size="sm" active>
126
+ <ArrowsUpDownIcon />
127
+ </ActionButton>
128
+ <ActionButton variant="icon" size="xs" active>
129
+ <ArrowsUpDownIcon />
130
+ </ActionButton>
131
+ </div>
132
+ </div>
133
+
134
+ <div className="flex flex-row justify-between">
135
+ <h6 className="w-[20px] text-white">Disabled:</h6>
136
+ <div className="flex flex-row gap-2">
137
+ <ActionButton variant="solid" size="lg" disabled>
138
+ <ArrowsUpDownIcon />
139
+ </ActionButton>
140
+ <ActionButton variant="solid" size="md" disabled>
141
+ <ArrowsUpDownIcon />
142
+ </ActionButton>
143
+ <ActionButton variant="solid" size="sm" disabled>
144
+ <ArrowsUpDownIcon />
145
+ </ActionButton>
146
+ </div>
147
+ <div className="flex flex-row gap-2">
148
+ <ActionButton variant="outline" size="lg" disabled>
149
+ <ArrowsUpDownIcon />
150
+ </ActionButton>
151
+ <ActionButton variant="outline" size="md" disabled>
152
+ <ArrowsUpDownIcon />
153
+ </ActionButton>
154
+ <ActionButton variant="outline" size="sm" disabled>
155
+ <ArrowsUpDownIcon />
156
+ </ActionButton>
157
+ </div>
158
+ <div className="flex flex-row gap-2">
159
+ <ActionButton variant="icon" size="lg" disabled>
160
+ <ArrowsUpDownIcon />
161
+ </ActionButton>
162
+ <ActionButton variant="icon" size="md" disabled>
163
+ <ArrowsUpDownIcon />
164
+ </ActionButton>
165
+ <ActionButton variant="icon" size="sm" disabled>
166
+ <ArrowsUpDownIcon />
167
+ </ActionButton>
168
+ <ActionButton variant="icon" size="xs" disabled>
169
+ <ArrowsUpDownIcon />
170
+ </ActionButton>
171
+ </div>
172
+ </div>
173
+ </div>
174
+ );
175
+ },
176
+ } satisfies StoryObj;
@@ -0,0 +1,79 @@
1
+ import { cva } from "class-variance-authority";
2
+
3
+ export const actionButtonVariants = cva(
4
+ ["bg-primary rounded box-border flex items-center justify-center"],
5
+ {
6
+ variants: {
7
+ variant: {
8
+ solid:
9
+ " bg-secondary-20 hover:bg-secondary-5 fill-secondary-foreground text-secondary-foreground",
10
+ outline: [
11
+ "bg-transparent border border-main-transparent-secondary-32 fill-secondary-70 text-secondary-70",
12
+ "hover:bg-main-transparent-secondary-8 hover:border-main-secondary-48 hover:fill-secondary-5 hover:text-secondary-5",
13
+ ],
14
+ icon: [
15
+ "rounded-full bg-transparent fill-secondary-70 text-secondary-70",
16
+ "hover:bg-main-transparent-secondary-8 hover:fill-secondary-5 hover:text-secondary-5",
17
+ ],
18
+ },
19
+ size: {
20
+ xs: "p-[2px] w-[18px] h-[18px]",
21
+ sm: "px-2 py-1 w-[38px] h-[30px]",
22
+ md: "px-3 py-2 w-[46px] h-[38px]",
23
+ lg: "px-4 py-3 w-[64px] h-[56px]",
24
+ },
25
+ disabled: {
26
+ true: "pointer-events-none border-grey2-500/[.32] text-grey2-500/[.32] fill-red-500",
27
+ },
28
+ active: {
29
+ false: "",
30
+ },
31
+ },
32
+ compoundVariants: [
33
+ {
34
+ variant: "solid",
35
+ disabled: true,
36
+ className: "bg-grey2-500 text-textcolor-medium fill-textcolor-medium",
37
+ },
38
+ {
39
+ variant: "solid",
40
+ active: true,
41
+ className:
42
+ "bg-primary-120 hover:bg-primary-100 text-primary-foreground",
43
+ },
44
+ {
45
+ variant: "outline",
46
+ active: true,
47
+ className:
48
+ "border-main-transparent-primary-48 hover:bg-main-transparent-primary-8 hover:text-primary text-primary",
49
+ },
50
+ {
51
+ variant: "icon",
52
+ active: true,
53
+ className:
54
+ "border-main-transparent-primary-48 hover:bg-main-transparent-primary-8 hover:text-primary text-primary",
55
+ },
56
+ {
57
+ size: "lg",
58
+ variant: "icon",
59
+ className: "w-[56px] h-[56px]",
60
+ },
61
+ {
62
+ size: "md",
63
+ variant: "icon",
64
+ className: "w-[38px] h-[38px]",
65
+ },
66
+ {
67
+ size: "sm",
68
+ variant: "icon",
69
+ className: "w-[30px] h-[30px]",
70
+ },
71
+ ],
72
+ defaultVariants: {
73
+ size: "md",
74
+ variant: "solid",
75
+ disabled: false,
76
+ active: false,
77
+ },
78
+ }
79
+ );
@@ -0,0 +1,42 @@
1
+ "use-client";
2
+
3
+ import { cn } from "@/utils/cn";
4
+ import React, { forwardRef } from "react";
5
+ import { actionButtonVariants } from "./ActionButton.styles";
6
+
7
+ export type ActionButtonProps = {
8
+ title?: string;
9
+ size?: "xs" | "sm" | "md" | "lg";
10
+ variant?: "solid" | "outline" | "icon";
11
+ disabled?: boolean;
12
+ active?: boolean;
13
+ children?: React.ReactNode;
14
+ className?: string;
15
+ } & React.ButtonHTMLAttributes<HTMLButtonElement>;
16
+
17
+ const ActionButton = forwardRef<HTMLButtonElement, ActionButtonProps>(
18
+ ({ children, disabled, active, className, size, variant, ...props }, ref) => {
19
+ const actionButtonClassname = actionButtonVariants({
20
+ size,
21
+ variant,
22
+ active,
23
+ disabled,
24
+ });
25
+
26
+ return (
27
+ <button
28
+ {...props}
29
+ ref={ref}
30
+ type="button"
31
+ aria-disabled={disabled || undefined}
32
+ disabled={disabled}
33
+ tabIndex={disabled ? -1 : 0}
34
+ className={cn(actionButtonClassname, className)}
35
+ >
36
+ {children}
37
+ </button>
38
+ );
39
+ }
40
+ );
41
+
42
+ export default ActionButton;
@@ -0,0 +1,107 @@
1
+ import React from "react";
2
+ import type { Meta, StoryObj } from "@storybook/react";
3
+
4
+ import Avatar, { AvatarProps } from "./Avatar";
5
+
6
+ const meta = {
7
+ title: "Components/Avatar/Avatar",
8
+ component: Avatar,
9
+ tags: ["autodocs"],
10
+ parameters: {
11
+ layout: "fullscreen",
12
+ },
13
+ decorators: [
14
+ (Story) => (
15
+ <div className="p-5">
16
+ <Story />
17
+ </div>
18
+ ),
19
+ ],
20
+ } satisfies Meta<typeof Avatar>;
21
+
22
+ export default meta;
23
+
24
+ export const Default = {
25
+ args: {
26
+ imageUrl: "",
27
+ text: "AN",
28
+ size: "lg",
29
+ rounded: "full",
30
+ },
31
+ render: (args) => {
32
+ console.log("args ", args);
33
+ const props: any = {
34
+ ...args,
35
+ };
36
+ return (
37
+ <div className="flex flex-row justify-between">
38
+ <Avatar {...props} />
39
+ </div>
40
+ );
41
+ },
42
+ } satisfies StoryObj;
43
+
44
+ export const Preview = {
45
+ args: {},
46
+ render: (args) => {
47
+ console.log("args ", args);
48
+ const props: typeof args = {
49
+ ...args,
50
+ };
51
+
52
+ const BORDER: AvatarProps["rounded"][] = ["full", "normal", "none"];
53
+
54
+ return (
55
+ <div className="flex flex-col gap-2 w-full bg-black p-20">
56
+ {BORDER.map((rounded) => (
57
+ <div key={rounded} className="flex flex-row items-center gap-3">
58
+ <Avatar
59
+ size="xxs"
60
+ rounded={rounded}
61
+ type="image"
62
+ imageUrl="https://i.pravatar.cc/300?img=59"
63
+ fallback="AS"
64
+ />
65
+ <Avatar
66
+ size="xs"
67
+ rounded={rounded}
68
+ type="image"
69
+ imageUrl="https://i.pravatar.cc/300?img=59"
70
+ fallback="AS"
71
+ />
72
+ <Avatar
73
+ size="sm"
74
+ rounded={rounded}
75
+ type="image"
76
+ imageUrl="https://i.pravatar.cc/300?img=59"
77
+ fallback="AS"
78
+ />
79
+ <Avatar
80
+ size="md"
81
+ rounded={rounded}
82
+ type="image"
83
+ imageUrl="https://i.pravatar.cc/300?img=59"
84
+ fallback="AS"
85
+ />
86
+ <Avatar
87
+ size="lg"
88
+ rounded={rounded}
89
+ type="image"
90
+ imageUrl="https://i.pravatar.cc/300?img=59"
91
+ fallback="AS"
92
+ />
93
+ </div>
94
+ ))}
95
+ {BORDER.map((rounded) => (
96
+ <div key={rounded} className="flex flex-row items-center gap-3">
97
+ <Avatar size="xxs" rounded={rounded} type="text" text="AS" />
98
+ <Avatar size="xs" rounded={rounded} type="text" text="AS" />
99
+ <Avatar size="sm" rounded={rounded} type="text" text="AS" />
100
+ <Avatar size="md" rounded={rounded} type="text" text="AS" />
101
+ <Avatar size="lg" rounded={rounded} type="text" text="AS" />
102
+ </div>
103
+ ))}
104
+ </div>
105
+ );
106
+ },
107
+ } satisfies StoryObj;
@@ -0,0 +1,28 @@
1
+ import { cva } from "class-variance-authority";
2
+
3
+ export const avatarVariants = cva(
4
+ [
5
+ "flex items-center justify-center bg-grey2-700 text-white typography-subtitile2 truncate",
6
+ ],
7
+ {
8
+ variants: {
9
+ size: {
10
+ xxs: "w-[24px] h-[24px] typography-subtitile3",
11
+ xs: "w-[32px] h-[32px]",
12
+ sm: "w-[40px] h-[40px]",
13
+ md: "w-[48px] h-[48px]",
14
+ lg: "w-[64px] h-[64px]",
15
+ },
16
+ rounded: {
17
+ normal: "rounded",
18
+ full: "rounded-full",
19
+ none: "rounded-none",
20
+ },
21
+ },
22
+
23
+ defaultVariants: {
24
+ size: "md",
25
+ rounded: "normal",
26
+ },
27
+ }
28
+ );
@@ -0,0 +1,88 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import { cn } from "@/utils/cn";
5
+ import { AvatarBase, AvatarFallback, AvatarImage } from "./AvatarBase";
6
+ import { avatarVariants } from "./Avatar.styles";
7
+
8
+ type BaseAvatarProps = {
9
+ imageUrl?: string;
10
+ text?: string;
11
+ fallback?: React.ReactNode;
12
+ icon?: React.ReactNode;
13
+ children?: React.ReactNode;
14
+ size?: "xxs" | "xs" | "sm" | "md" | "lg";
15
+ rounded?: "full" | "normal" | "none";
16
+ className?: string;
17
+ imageClassName?: string;
18
+ fallbackClassName?: string;
19
+ style?: React.CSSProperties;
20
+ };
21
+
22
+ type AvatarText = {
23
+ text: string;
24
+ type: "text";
25
+ } & BaseAvatarProps;
26
+
27
+ type AvatarImage = {
28
+ imageUrl: string;
29
+ fallback: React.ReactNode;
30
+ type: "image";
31
+ } & BaseAvatarProps;
32
+
33
+ type AvatarIcon = {
34
+ icon: string;
35
+ type: "icon";
36
+ } & BaseAvatarProps;
37
+
38
+ export type AvatarProps = AvatarText | AvatarImage | AvatarIcon;
39
+
40
+ export const formatAvatarName = (text: string) => {
41
+ if (!text.length) return "-";
42
+
43
+ const spitWithSpace = text.split(" ");
44
+ const first = text?.charAt(0);
45
+ const last = spitWithSpace?.[1]?.charAt(0) ?? text?.charAt(1) ?? "";
46
+
47
+ return `${first}${last}`;
48
+ };
49
+
50
+ const Avatar: React.FC<AvatarProps> = ({
51
+ text,
52
+ imageUrl,
53
+ icon,
54
+ fallback,
55
+ size,
56
+ rounded,
57
+ className,
58
+ imageClassName,
59
+ fallbackClassName,
60
+ type = "text",
61
+ children,
62
+ style,
63
+ }) => {
64
+ const avatarClassname = avatarVariants({ size, rounded });
65
+
66
+ return (
67
+ <AvatarBase className={cn(avatarClassname, className)} style={style}>
68
+ {children || (
69
+ <>
70
+ {type === "image" && (
71
+ <>
72
+ <AvatarImage src={imageUrl} className={cn(imageClassName)} />
73
+ <AvatarFallback className={cn(fallbackClassName)}>
74
+ {typeof fallback === "string"
75
+ ? formatAvatarName(fallback)
76
+ : fallback}
77
+ </AvatarFallback>
78
+ </>
79
+ )}
80
+ {type === "text" && formatAvatarName(text ?? "")}
81
+ {type === "icon" && icon}
82
+ </>
83
+ )}
84
+ </AvatarBase>
85
+ );
86
+ };
87
+
88
+ export default Avatar;
@@ -0,0 +1,50 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import * as AvatarPrimitive from "@radix-ui/react-avatar";
5
+
6
+ import { cn } from "@/utils/cn";
7
+
8
+ const AvatarBase = React.forwardRef<
9
+ React.ElementRef<typeof AvatarPrimitive.Root>,
10
+ React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
11
+ >(({ className, ...props }, ref) => (
12
+ <AvatarPrimitive.Root
13
+ ref={ref}
14
+ className={cn(
15
+ "relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
16
+ className
17
+ )}
18
+ {...props}
19
+ />
20
+ ));
21
+ AvatarBase.displayName = AvatarPrimitive.Root.displayName;
22
+
23
+ const AvatarImage = React.forwardRef<
24
+ React.ElementRef<typeof AvatarPrimitive.Image>,
25
+ React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
26
+ >(({ className, ...props }, ref) => (
27
+ <AvatarPrimitive.Image
28
+ ref={ref}
29
+ className={cn("aspect-square h-full w-full", className)}
30
+ {...props}
31
+ />
32
+ ));
33
+ AvatarImage.displayName = AvatarPrimitive.Image.displayName;
34
+
35
+ const AvatarFallback = React.forwardRef<
36
+ React.ElementRef<typeof AvatarPrimitive.Fallback>,
37
+ React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
38
+ >(({ className, ...props }, ref) => (
39
+ <AvatarPrimitive.Fallback
40
+ ref={ref}
41
+ className={cn(
42
+ "flex h-full w-full items-center justify-center rounded-full bg-muted",
43
+ className
44
+ )}
45
+ {...props}
46
+ />
47
+ ));
48
+ AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
49
+
50
+ export { AvatarBase, AvatarImage, AvatarFallback };
@@ -0,0 +1,77 @@
1
+ import React from "react";
2
+ import type { Meta, StoryObj } from "@storybook/react";
3
+
4
+ import AvatarGroup from "./AvatarGroup";
5
+ import Avatar from "./Avatar";
6
+
7
+ const meta = {
8
+ title: "Components/Avatar/AvatarGroup",
9
+ component: AvatarGroup,
10
+ tags: ["autodocs"],
11
+ parameters: {
12
+ layout: "fullscreen",
13
+ },
14
+ decorators: [
15
+ (Story) => (
16
+ <div className="p-5">
17
+ <Story />
18
+ </div>
19
+ ),
20
+ ],
21
+ } satisfies Meta<typeof AvatarGroup>;
22
+
23
+ export default meta;
24
+
25
+ export const Default = {
26
+ args: {
27
+ imageUrl: "",
28
+ text: "AN",
29
+ size: "lg",
30
+ rounded: "full",
31
+ },
32
+ render: (args) => {
33
+ console.log("args ", args);
34
+ const props: any = {
35
+ ...args,
36
+ };
37
+ return (
38
+ <div className="flex flex-row justify-between">
39
+ <AvatarGroup {...props}>
40
+ <Avatar size="lg" rounded="full" type="text" text="AS" />
41
+ <Avatar size="lg" rounded="full" type="text" text="AS" />
42
+ <Avatar size="lg" rounded="full" type="text" text="AS" />
43
+ </AvatarGroup>
44
+ </div>
45
+ );
46
+ },
47
+ } satisfies StoryObj;
48
+
49
+ export const Preview = {
50
+ args: {},
51
+ render: (args) => {
52
+ console.log("args ", args);
53
+ const props: typeof args = {
54
+ ...args,
55
+ };
56
+
57
+ return (
58
+ <div className="flex flex-col gap-2 w-full bg-black p-20">
59
+ <div className="flex flex-row items-center gap-3">
60
+ <AvatarGroup>
61
+ <Avatar size="lg" rounded="full" type="text" text="AS" />
62
+ <Avatar size="lg" rounded="full" type="text" text="AS" />
63
+ <Avatar
64
+ size="lg"
65
+ rounded="full"
66
+ type="image"
67
+ imageUrl="https://i.pravatar.cc/300?img=59"
68
+ fallback="AS"
69
+ />
70
+ <Avatar size="lg" rounded="full" type="text" text="AS" />
71
+ <Avatar size="lg" rounded="full" type="text" text="AS" />
72
+ </AvatarGroup>
73
+ </div>
74
+ </div>
75
+ );
76
+ },
77
+ } satisfies StoryObj;