Skip to content

Commit

Permalink
chore(core): add <AvatarSkeleton /> component (#8249)
Browse files Browse the repository at this point in the history
pedrobonamin authored Jan 13, 2025

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 885cfe0 commit 0ab9c5b
Showing 3 changed files with 30 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -121,7 +121,7 @@ const StyledText = styled(Text)`
*/
export function LoadingBlock({fill, showText, title}: LoadingTestProps) {
return (
<StyledCard $fill={fill} as={fill ? Layer : 'div'}>
<StyledCard $fill={fill} as={fill ? Layer : 'div'} data-testid="loading-block">
<StyledSpinner $animatePosition={!!showText} muted />
{showText && <LoadingText title={title} />}
</StyledCard>
30 changes: 27 additions & 3 deletions packages/sanity/src/core/components/userAvatar/UserAvatar.tsx
Original file line number Diff line number Diff line change
@@ -5,14 +5,36 @@ import {
type AvatarProps,
type AvatarSize,
type AvatarStatus,
Skeleton,
} from '@sanity/ui'
// eslint-disable-next-line camelcase
import {getTheme_v2} from '@sanity/ui/theme'
import {type ForwardedRef, forwardRef, useState} from 'react'
import {css, styled} from 'styled-components'

import {Tooltip} from '../../../ui-components'
import {useUser} from '../../store'
import {useUserColor} from '../../user-color'
import {isRecord} from '../../util'

interface AvatarSkeletonProps {
$size?: AvatarSize
}

/**
* A loading skeleton element representing a user avatar
* @beta
*/
export const AvatarSkeleton = styled(Skeleton)<AvatarSkeletonProps>((props) => {
const theme = getTheme_v2(props.theme)
const size = props.$size ?? 1
return css`
border-radius: 50%;
width: ${theme.avatar.sizes[size].size}px;
height: ${theme.avatar.sizes[size].size}px;
`
})

/**
* @hidden
* @beta */
@@ -106,11 +128,13 @@ const StaticUserAvatar = forwardRef(function StaticUserAvatar(
})

function UserAvatarLoader({user, ...loadedProps}: Omit<UserAvatarProps, 'user'> & {user: string}) {
const [value] = useUser(user)
const [value, loading] = useUser(user)

if (loading) {
return <AvatarSkeleton $size={loadedProps.size} animated />
}
if (!value) {
// @todo How do we handle this?
return null
return <AvatarSkeleton $size={loadedProps.size} animated={false} />
}

return <UserAvatar {...loadedProps} user={value} />
14 changes: 2 additions & 12 deletions packages/sanity/src/core/tasks/components/TasksUserAvatar.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import {UserIcon} from '@sanity/icons'
import {type User} from '@sanity/types'
import {type AvatarSize, Skeleton, Text} from '@sanity/ui'
import {type AvatarSize, Text} from '@sanity/ui'
// eslint-disable-next-line camelcase
import {getTheme_v2} from '@sanity/ui/theme'
import {css, styled} from 'styled-components'

import {Tooltip} from '../../../ui-components'
import {UserAvatar} from '../../components'
import {AvatarSkeleton, UserAvatar} from '../../components'
import {useUser} from '../../store'

const AvatarRoot = styled.div<{$size: AvatarSize; $border?: boolean; $removeBg?: boolean}>(
@@ -25,16 +25,6 @@ const AvatarRoot = styled.div<{$size: AvatarSize; $border?: boolean; $removeBg?:
},
)

const AvatarSkeleton = styled(Skeleton)<{$size: AvatarSize}>((props) => {
const theme = getTheme_v2(props.theme)

return css`
height: ${theme.avatar.sizes[props.$size]?.size}px;
width: ${theme.avatar.sizes[props.$size]?.size}px;
border-radius: 50%;
`
})

export function TasksUserAvatar(props: {
user?: User
size?: AvatarSize

0 comments on commit 0ab9c5b

Please sign in to comment.