Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Avatar): create component, theme, and stories #9868

Merged
merged 16 commits into from
Jul 19, 2023
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
07184d7
feat(Avatar): create component, theme, and stories
TylerAPfledderer Apr 3, 2023
2ad0caa
Merge branch 'dev' into feat/new-avatar-theme
TylerAPfledderer Apr 14, 2023
a6fa557
Merge remote-tracking branch 'origin/dev' into feat/new-avatar-theme
TylerAPfledderer Jun 18, 2023
6026788
refactor(theme/Avatar): apply nested semantic update
TylerAPfledderer Jun 18, 2023
e0092ac
refactor(theme/avatar): remove 2xs size and clarify default usage
TylerAPfledderer Jun 18, 2023
c5c0a04
chore(theme/avatar): remove unused CSS var
TylerAPfledderer Jun 18, 2023
275c1bf
fix(theme/avatar): update semantic color for excess label background
TylerAPfledderer Jun 18, 2023
13b3141
style(avatar): change color for link text to primary semantic
TylerAPfledderer Jun 18, 2023
999039f
Merge remote-tracking branch 'origin/dev' into feat/new-avatar-theme
TylerAPfledderer Jun 30, 2023
005ca63
chore(theme/semanticTokens): remove duplicate `buttonHover` token
TylerAPfledderer Jun 30, 2023
41f070d
refactor(theme/Avatar): provide custom `boxShadow` for hover
TylerAPfledderer Jun 30, 2023
f76ec44
refactor(Avatar): adjust gaps with link text
TylerAPfledderer Jul 1, 2023
225d4d8
Merge remote-tracking branch 'origin/dev' into feat/new-avatar-theme
TylerAPfledderer Jul 16, 2023
ae801d9
Merge remote-tracking branch 'origin/dev' into feat/new-avatar-theme
TylerAPfledderer Jul 19, 2023
e4957d3
Merge branch 'dev' into pr/TylerAPfledderer/9868
pettinarip Jul 19, 2023
a76ae3e
Update src/components/Avatar/index.tsx
TylerAPfledderer Jul 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions src/@chakra-ui/gatsby-plugin/components/Avatar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import {
createMultiStyleConfigHelpers,
cssVar,
defineStyle,
getToken,
} from "@chakra-ui/react"
import { avatarAnatomy } from "@chakra-ui/anatomy"
import { avatarDefaultTheme, defineMergeStyles } from "./components.utils"
import { pick } from "lodash"

const { defineMultiStyleConfig, definePartsStyle } =
createMultiStyleConfigHelpers(avatarAnatomy.keys)

const { baseStyle: defaultBaseStyle, sizes: defaultSizes } = avatarDefaultTheme

const $border = cssVar("avatar-border-color", "transparent")
const $mlBySize = cssVar("ml-by-size")

const baseStyleContainer = defineStyle((props) => {
const primaryLowContrast = getToken(
"colors",
"primary.lowContrast"
)(props.theme)

return defineMergeStyles(defaultBaseStyle?.(props).container, {
[$border.variable]: "transparent",
borderWidth: "1px",
"&:hover, [data-peer]:hover ~ &": {
boxShadow: `0.15em 0.15em 0 ${primaryLowContrast}`,
},
_focus: {
outline: "4px solid",
outlineColor: "primary.hover",
outlineOffset: "-1px",
},
_active: {
[$border.variable]: "colors.primary.hover",
boxShadow: "none",
"& img": {
opacity: 0.7,
},
},
"[role='group'] &": {
[$border.variable]: "colors.background.base",
_notLast: {
marginLeft: $mlBySize.reference,
},
},
})
})

const baseStyleExessLabel = defineStyle((props) =>
defineMergeStyles(defaultBaseStyle?.(props).excessLabel, {
bg: "body.base",
color: "background.base",
ms: $mlBySize.reference,
})
)

const baseStyle = definePartsStyle((props) => ({
container: baseStyleContainer(props),
excessLabel: baseStyleExessLabel(props),
}))

const USED_SIZES = ["xs", "sm", "md", "lg"] as const

const pickedDefaultSizes: { [k in (typeof USED_SIZES)[number]]?: object } =
pick(defaultSizes, ...USED_SIZES)

const sizes = defineMergeStyles(pickedDefaultSizes, {
xs: {
group: {
[$mlBySize.variable]: "space.-1",
},
excessLabel: {
fontSize: "0.563rem",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious about this value. How did you get it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the DS for the xs size avatar, the excess label is showing a font size of 9px which is this in rem.

This value is not a part of the default fontSize tokens. 2xs in the default theme is 0.625rem, and 3xs is 0.45rem.

},
},
sm: {
group: {
[$mlBySize.variable]: "space.-2",
},
excessLabel: {
fontSize: "sm",
},
},
})

export const Avatar = defineMultiStyleConfig({
baseStyle,
// @ts-expect-error
sizes,
})
4 changes: 2 additions & 2 deletions src/@chakra-ui/gatsby-plugin/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Avatar } from "./Avatar"
import { Badge } from "./Badge"
import { Button } from "./Button"
import { Link } from "./Link"
Expand All @@ -12,7 +13,6 @@ import { Switch } from "./Switch"
import { Input } from "./Input"
import {
accordionDefaultTheme,
avatarDefaultTheme,
breadcrumbDefaultTheme,
closeButtonDefaultTheme,
codeDefaultTheme,
Expand All @@ -28,7 +28,7 @@ import {

export default {
Accordion: accordionDefaultTheme,
Avatar: avatarDefaultTheme,
Avatar,
Badge,
Breadcrumb: breadcrumbDefaultTheme,
Button,
Expand Down
6 changes: 0 additions & 6 deletions src/@chakra-ui/gatsby-plugin/semanticTokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,6 @@ const semanticTokens = {
"linear-gradient(102.7deg, rgba(185, 185, 241, 0.2) 0%, rgba(84, 132, 234, 0.2) 51.56%, rgba(58, 142, 137, 0.2) 100%)",
},
},
shadows: {
buttonHover: {
_light: "4px 4px 0 var(--eth-colors-blue-100)",
_dark: "4px 4px 0 #352313",
},
},
}

export default semanticTokens
73 changes: 73 additions & 0 deletions src/components/Avatar/Avatar.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import * as React from "react"
import { Meta, StoryObj } from "@storybook/react"
import { VStack, AvatarGroup, HStack } from "@chakra-ui/react"
import Avatar from "."

type AvatarType = typeof Avatar

const meta: Meta<AvatarType> = {
title: "Atoms / Media & Icons / Avatars",
component: Avatar,
}

export default meta

type Story = StoryObj<AvatarType>

export const Single: Story = {
args: {
name: "Dan Abrahmov",
src: "https://bit.ly/dan-abramov",
href: "#",
},
render: (args) => (
<VStack spacing={4}>
{["lg", "md", "sm", "xs"].map((size) => (
<Avatar key={size} size={size} {...args} />
))}
</VStack>
),
}

export const Group: Story = {
args: {
name: "Dan Abrahmov",
src: "https://bit.ly/dan-abramov",
href: "#",
},
render: (args) => (
<VStack spacing={4}>
{["sm", "xs"].map((size) => (
<AvatarGroup key={size} size={size} max={3}>
<Avatar {...args} />
<Avatar {...args} />
<Avatar {...args} />
<Avatar {...args} />
</AvatarGroup>
))}
</VStack>
),
}

export const WithUsername: Story = {
args: {
name: "Dan Abrahmov",
src: "https://bit.ly/dan-abramov",
href: "#",
label: "daneabrahmov",
},
render: (args) => (
<HStack spacing={16}>
<VStack>
{["md", "sm"].map((size) => (
<Avatar size={size} {...args} />
))}
</VStack>
<VStack>
{["md", "sm"].map((size) => (
<Avatar size={size} direction="column" {...args} />
))}
</VStack>
</HStack>
),
}
77 changes: 77 additions & 0 deletions src/components/Avatar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import * as React from "react"
import {
Avatar as ChakraAvatar,
AvatarProps,
Center,
CenterProps,
FlexProps,
forwardRef,
Link,
LinkBox,
LinkOverlay,
LinkProps,
ThemingProps,
} from "@chakra-ui/react"
import { RxExternalLink } from "react-icons/rx"

type AssignAvatarProps = Required<Pick<AvatarProps, "name" | "src">> &
AvatarProps

type AvatarLinkProps = AssignAvatarProps &
Pick<LinkProps, "href"> &
ThemingProps<"Avatar"> & {
label?: string
direction?: "column" | "row"
}

const Avatar = forwardRef<AvatarLinkProps, "div" | "a">((props, ref) => {
const { href, src, name, size = "md", label, direction = "row" } = props

const avatarProps = {
src,
name,
size,
}

const linkProps = {
href,
isExternal: true,
color: "primary.base",
}

if (label) {
const _direction: "column-reverse" | "row-reverse" = `${direction}-reverse`
return (
<LinkBox as={Center} ref={ref} flexDirection={_direction} columnGap="1">
<LinkOverlay
as={Link}
data-peer
display="inline-flex"
textDecoration="none"
alignItems="center"
gap="1"
p="1"
fontSize={size !== "md" ? "12px" : "14px"}
TylerAPfledderer marked this conversation as resolved.
Show resolved Hide resolved
zIndex="overlay"
{...linkProps}
>
{label}
<RxExternalLink />
</LinkOverlay>
<ChakraAvatar {...avatarProps} />
</LinkBox>
)
}

return (
<ChakraAvatar
as={Link}
ref={ref}
showBorder
{...avatarProps}
{...linkProps}
/>
)
})

export default Avatar