diff --git a/.gitignore b/.gitignore index 3fcf6ae..e1fc775 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ # Dependency directories node_modules/ .turbo -.DS_Store \ No newline at end of file +.DS_Store + +# pnpm +.pnpm-debug.log \ No newline at end of file diff --git a/docs/docs/components/avatar.mdx b/docs/docs/components/avatar.mdx new file mode 100644 index 0000000..2f9f268 --- /dev/null +++ b/docs/docs/components/avatar.mdx @@ -0,0 +1,220 @@ +# Avatar + +### Quick start + +Hover avatar component can be used to display profile pictures. It supports images, icons or letters. Here's a quick start guide to get started with the avatar component + +### Importing Component + +import "@hover-design/react/dist/style.css"; +import { Avatar, AvatarGroup, Flex, Card } from "@hover-design/react"; + +export const Avatarcontainer = ({ children }) => ( + + + {children} + + +); + +```jsx +import { Avatar } from "@hover-design/react"; +``` + +### Code Snippets and Examples + +##### Avatars with Image + +``` +
+ + + +
+ +``` + + + + + + + +##### Avatars without Image + +``` +
+ J + RA + +3 +
+ +``` + + + + J + + + RA + + + +3 + + + +##### Avatars with sizes + +``` +
+ + + + + +
+ +``` + + + + + + + + + +##### Avatars with shapes + +``` +
+ + + + + +
+ +``` + + + + + + + + + +##### AvatarGroups + +``` +
+ + + + + +5 + +
+ +``` + + + + + + + + +5 + + + + +### Avatar Props Referece + +| Attributes | Values | Optional ? | +| :----------- | :-----------------------------: | ---------: | +| src | `string` | Yes | +| alt | `string` | Yes | +| borderRadius | `xs` `sm` `md` `lg` `xl` number | Yes | +| size | `xs` `sm` `md` `lg` `xl` number | Yes | +| color | `string` | Yes | +| textColor | `string` | Yes | +| ref | `RefObject;` | Yes | + +### Avatar.Group Props Referece + +| Attributes | Values | Optional ? | +| :--------- | :--------------: | ---------: | +| children | `React.Children` | No | +| gap | `string` | Yes | + +
+ +> **Note:** As of now any custom props (classNames, html attributes, etc) added, will be applied only for the wrappers and not for the img tag. diff --git a/lib/src/components/Avatar/Avatar.tsx b/lib/src/components/Avatar/Avatar.tsx new file mode 100644 index 0000000..cb3a5b1 --- /dev/null +++ b/lib/src/components/Avatar/Avatar.tsx @@ -0,0 +1,59 @@ +import React, { ForwardRefRenderFunction } from "react"; +import { IAvatarProps } from "./avatar.types"; +import { + avatarImg, + avatarThemeClass, + avatarThemeVars, + avatarShapes, + avatarSizes, + avatarWrapper +} from "./avatar.styles.css"; +import { assignInlineVars } from "@vanilla-extract/dynamic"; +import { Flex } from "../Flex"; + +const AvatarComponent: ForwardRefRenderFunction< + HTMLDivElement, + IAvatarProps +> = ( + { + children, + src, + alt, + borderRadius = "xl", + size = "md", + color = "#000", + textColor = "#fff", + className, + style, + ...nativeProps + }, + ref +) => { + const assignVariables = assignInlineVars({ + [avatarThemeVars.avatarStyleColor]: src ? "transparent" : color, + [avatarThemeVars.avatarStyleTextColor]: textColor, + [avatarThemeVars.avatarStyleBorderRadius]: avatarShapes[borderRadius] + ? avatarShapes[borderRadius] + : borderRadius, + [avatarThemeVars.avatarStyleSize]: avatarSizes[size] + ? avatarSizes[size] + : size + }); + + return ( + + {src ? {alt} : children} + + ); +}; + +const AvatarWithRef = React.forwardRef(AvatarComponent); +export { AvatarWithRef as Avatar }; diff --git a/lib/src/components/Avatar/AvatarGroup/AvatarGroup.tsx b/lib/src/components/Avatar/AvatarGroup/AvatarGroup.tsx new file mode 100644 index 0000000..5c1fbee --- /dev/null +++ b/lib/src/components/Avatar/AvatarGroup/AvatarGroup.tsx @@ -0,0 +1,37 @@ +import React, { ForwardRefRenderFunction } from "react"; +import { Flex } from "src/components/Flex"; +import { IAvatarGroupProps } from "../avatar.types"; +import { assignInlineVars } from "@vanilla-extract/dynamic"; +import { + avatarChildClass, + avatarGaps, + avatarGroupThemeClass, + avatarGroupThemeVars +} from "../avatar.styles.css"; +import "../avatar.global.styles.css"; + +const AvatarGroup: ForwardRefRenderFunction< + HTMLDivElement, + IAvatarGroupProps +> = ({ children, gap = "xs", className, style, ...nativeProps }, ref) => { + const assignVariables = assignInlineVars({ + [avatarGroupThemeVars.avatarStyleGap]: avatarGaps[gap] + }); + + return ( + + {children} + + ); +}; + +const AvatarGroupWithRef = React.forwardRef(AvatarGroup); +export { AvatarGroupWithRef as AvatarGroup }; diff --git a/lib/src/components/Avatar/avatar.global.styles.css.ts b/lib/src/components/Avatar/avatar.global.styles.css.ts new file mode 100644 index 0000000..e4d4e89 --- /dev/null +++ b/lib/src/components/Avatar/avatar.global.styles.css.ts @@ -0,0 +1,6 @@ +import { globalStyle } from "@vanilla-extract/css"; +import { avatarChildClass, avatarGroupThemeVars } from "./avatar.styles.css"; + +globalStyle(`${avatarChildClass} > div:not(:first-child)`, { + marginLeft: avatarGroupThemeVars.avatarStyleGap +}); diff --git a/lib/src/components/Avatar/avatar.styles.css.ts b/lib/src/components/Avatar/avatar.styles.css.ts new file mode 100644 index 0000000..8573c99 --- /dev/null +++ b/lib/src/components/Avatar/avatar.styles.css.ts @@ -0,0 +1,61 @@ +import { style, createTheme } from "@vanilla-extract/css"; +import { IAvatarGroupTheme, IAvatarTheme } from "./avatar.types"; + +export const avatarGaps: Record< + IAvatarGroupTheme[1]["avatarStyleGap"], + string +> = { + xs: "-16px", + sm: "-14px", + md: "-12px", + lg: "-10px", + xl: "-8px" +}; + +export const avatarChildClass = style({}); + +export const [avatarGroupThemeClass, avatarGroupThemeVars]: IAvatarGroupTheme = + createTheme({ avatarStyleGap: "0" }); + +export const [avatarThemeClass, avatarThemeVars]: IAvatarTheme = createTheme({ + avatarStyleColor: "none", + avatarStyleTextColor: "inherit", + avatarStyleBorderRadius: "0", + avatarStyleSize: "0" +}); + +export const avatarImg = style({ + objectFit: "cover", + width: "100%", + height: "100%" +}); + +export const avatarSizes: Record = { + xs: "16px", + sm: "24px", + md: "32px", + lg: "40px", + xl: "48px" +}; + +export const avatarShapes: Record< + IAvatarTheme[1]["avatarStyleBorderRadius"], + string +> = { + xs: "2px", + sm: "4px", + md: "8px", + lg: "16px", + xl: "32px" +}; + +export const avatarWrapper = style({ + fontWeight: "700", + verticalAlign: "middle", + overflow: "hidden", + width: avatarThemeVars.avatarStyleSize, + height: avatarThemeVars.avatarStyleSize, + backgroundColor: avatarThemeVars.avatarStyleColor, + color: avatarThemeVars.avatarStyleTextColor, + borderRadius: avatarThemeVars.avatarStyleBorderRadius +}); diff --git a/lib/src/components/Avatar/avatar.types.ts b/lib/src/components/Avatar/avatar.types.ts new file mode 100644 index 0000000..d717eab --- /dev/null +++ b/lib/src/components/Avatar/avatar.types.ts @@ -0,0 +1,39 @@ +import { MutableRefObject, ReactNode } from "react"; + +export type IAvatarSizes = "xs" | "sm" | "md" | "lg" | "xl"; + +export type IAvatarShapes = "xs" | "sm" | "md" | "lg" | "xl"; + +export type IAvatarGaps = "xs" | "sm" | "md" | "lg" | "xl"; + +export type IAvatarGroupProps = JSX.IntrinsicElements["div"] & { + ref?: MutableRefObject; + children?: ReactNode; + gap?: string; +}; + +export type IAvatarGroupTheme = [ + string, + { avatarStyleGap: IAvatarGaps | string } +]; + +export type IAvatarProps = JSX.IntrinsicElements["div"] & { + src?: string; + alt?: string; + borderRadius?: string; + size?: string; + color?: string; + textColor?: string; + ref?: MutableRefObject; + children?: ReactNode; +}; + +export type IAvatarTheme = [ + string, + { + avatarStyleColor: string; + avatarStyleTextColor: string; + avatarStyleBorderRadius: IAvatarShapes | string; + avatarStyleSize: IAvatarSizes | string; + } +]; diff --git a/lib/src/components/Avatar/index.ts b/lib/src/components/Avatar/index.ts new file mode 100644 index 0000000..0aae172 --- /dev/null +++ b/lib/src/components/Avatar/index.ts @@ -0,0 +1,3 @@ +export * from "./Avatar"; +export * from "./avatar.styles.css"; +export * from "./AvatarGroup/AvatarGroup"; diff --git a/lib/src/index.ts b/lib/src/index.ts index d826dff..a92d542 100644 --- a/lib/src/index.ts +++ b/lib/src/index.ts @@ -11,4 +11,4 @@ export * from "./components/Divider"; export * from "./components/Icon"; export * from "./components/TextArea"; export * from "./components/Tab"; - +export * from "./components/Avatar";