Skip to content

Commit

Permalink
feat(Avatar): Remove the CSS modules feature flag from Avatar (#5221)
Browse files Browse the repository at this point in the history
* Refactor Avatar component to only use CSS modules

* Use empty string

* Create dirty-dodos-applaud.md

* ref

* Remove ts-ignore

* Update snapshot

* Remove ref from args

* Pass in as prop

* Add className to type

* Add React.ComponentPropsWithoutRef<'img'>

* Remove HTMLProps

* Remove unused as

* skip as
  • Loading branch information
jonrohan authored Nov 7, 2024
1 parent 307e706 commit 11c455c
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 174 deletions.
5 changes: 5 additions & 0 deletions .changeset/dirty-dodos-applaud.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/react": minor
---

Remove the CSS modules feature flag from Avatar
6 changes: 0 additions & 6 deletions packages/react/src/Avatar/Avatar.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,6 @@ Playground.argTypes = {
disable: true,
},
},
ref: {
controls: false,
table: {
disable: true,
},
},
sx: {
controls: false,
table: {
Expand Down
103 changes: 27 additions & 76 deletions packages/react/src/Avatar/Avatar.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
import {clsx} from 'clsx'
import React from 'react'
import Box from '../Box'
import styled from 'styled-components'
import {get} from '../constants'
import type {BetterCssProperties, BetterSystemStyleObject, SxProp} from '../sx'
import sx, {merge} from '../sx'
import type {ComponentProps} from '../utils/types'
import type {SxProp} from '../sx'
import type {ResponsiveValue} from '../hooks/useResponsiveValue'
import {isResponsiveValue} from '../hooks/useResponsiveValue'
import {getBreakpointDeclarations} from '../utils/getBreakpointDeclarations'
import {defaultSxProp} from '../utils/defaultSxProp'
import classes from './Avatar.module.css'
import {useFeatureFlag} from '../FeatureFlags'

export const DEFAULT_AVATAR_SIZE = 20

type StyledAvatarProps = {
export type AvatarProps = {
/** Sets the width and height of the avatar. */
size?: number | ResponsiveValue<number>
/** Sets the shape of the avatar to a square if true. If false, the avatar will be circular. */
Expand All @@ -24,99 +18,56 @@ type StyledAvatarProps = {
src: string
/** Provide alt text when the Avatar is used without the user's name next to it. */
alt?: string
} & SxProp

const StyledAvatar = styled.img.attrs<StyledAvatarProps>(props => ({
height: props.size,
width: props.size,
}))<StyledAvatarProps>`
display: inline-block;
overflow: hidden; // Ensure page layout in Firefox should images fail to load
line-height: ${get('lineHeights.condensedUltra')};
vertical-align: middle;
// If the avatar is square and size is greater than 24px (at any breakpoint), border-radius will be 6px. Otherwise, it will be 4px.
border-radius: ${props => (props.square ? 'clamp(4px, var(--avatar-size) - 24px, 6px)' : '50%')};
box-shadow: 0 0 0 1px ${get('colors.avatar.border')};
height: var(--avatar-size);
width: var(--avatar-size);
${sx}
`

export type AvatarProps = ComponentProps<typeof StyledAvatar>
/** Additional class name. */
className?: string
} & SxProp &
React.ComponentPropsWithoutRef<'img'>

const Avatar = React.forwardRef<HTMLImageElement, AvatarProps>(function Avatar(
{alt = '', size = DEFAULT_AVATAR_SIZE, square = false, sx: sxProp = defaultSxProp, className, ...rest},
ref,
) {
const enabled = useFeatureFlag('primer_react_css_modules_ga')
const isResponsive = isResponsiveValue(size)
const avatarSx = isResponsive
? merge<BetterCssProperties | BetterSystemStyleObject>(
getBreakpointDeclarations(
size,
'--avatar-size' as keyof React.CSSProperties,
value => `${value || DEFAULT_AVATAR_SIZE}px`,
),
sxProp as SxProp,
)
: merge({'--avatar-size': `${size}px`} as React.CSSProperties, sxProp as SxProp)

if (enabled) {
const cssSizeVars = {} as Record<string, string>
const cssSizeVars = {} as Record<string, string>

if (isResponsive) {
for (const [key, value] of Object.entries(size)) {
cssSizeVars[`--avatarSize-${key}`] = `${value}px`
}
} else {
cssSizeVars['--avatarSize-regular'] = `${size}px`
}

if (sxProp !== defaultSxProp) {
return (
<Box
as="img"
data-component="Avatar"
className={clsx(className, classes.Avatar)}
ref={ref}
alt={alt}
data-responsive={isResponsive ? '' : undefined}
data-square={square ? '' : undefined}
width={isResponsive ? undefined : size}
height={isResponsive ? undefined : size}
// @ts-ignore - it's not allowing CSS properties here
style={cssSizeVars as React.CSSProperties}
sx={sxProp}
{...rest}
/>
)
if (isResponsive) {
for (const [key, value] of Object.entries(size)) {
cssSizeVars[`--avatarSize-${key}`] = `${value}px`
}
} else {
cssSizeVars['--avatarSize-regular'] = `${size}px`
}

if (sxProp !== defaultSxProp) {
return (
<img
<Box
as={'img'}
data-component="Avatar"
className={clsx(className, classes.Avatar)}
ref={ref}
alt={alt}
data-responsive={isResponsive ? 'true' : undefined}
data-square={square ? 'true' : undefined}
data-responsive={isResponsive ? '' : undefined}
data-square={square ? '' : undefined}
width={isResponsive ? undefined : size}
height={isResponsive ? undefined : size}
// @ts-ignore - it's not allowing CSS properties here
style={cssSizeVars as React.CSSProperties}
sx={sxProp}
{...rest}
/>
)
}

return (
<StyledAvatar
<img
data-component="Avatar"
className={className}
className={clsx(className, classes.Avatar)}
ref={ref}
alt={alt}
size={size}
square={square}
sx={avatarSx}
data-responsive={isResponsive ? '' : undefined}
data-square={square ? '' : undefined}
width={isResponsive ? undefined : size}
height={isResponsive ? undefined : size}
style={cssSizeVars as React.CSSProperties}
{...rest}
/>
)
Expand Down
Loading

0 comments on commit 11c455c

Please sign in to comment.