static/app/components/core/avatar/avatar.mdx
import {Fragment} from 'react';
import {Flex} from '@sentry/scraps/layout';
import {Placeholder} from 'sentry/components/placeholder'; import * as Storybook from 'sentry/stories'; import {useMembers} from 'sentry/utils/members/useMembers'; import {useUserTeams} from 'sentry/utils/useUserTeams';
import { AvatarList, DocIntegrationAvatar, OrganizationAvatar, ProjectAvatar, SentryAppAvatar, TeamAvatar, UserAvatar, } from '@sentry/scraps/avatar';
import { DOC_INTEGRATION, ORGANIZATION, PREVIEW_SIZE, PROJECT, SENTRY_APP, TEAM, USER, } from './stories/fixtures';
export const documentation = import('!!type-loader!@sentry/scraps/avatar');
There are multiple avatar components which represent users, teams, organizations, projects, and integrations.
<Storybook.Demo> <UserAvatar size={PREVIEW_SIZE} user={USER} /> <TeamAvatar size={PREVIEW_SIZE} team={TEAM} /> <ProjectAvatar size={PREVIEW_SIZE} project={PROJECT} /> <OrganizationAvatar size={PREVIEW_SIZE} organization={ORGANIZATION} /> <SentryAppAvatar size={PREVIEW_SIZE} sentryApp={SENTRY_APP} /> <DocIntegrationAvatar size={PREVIEW_SIZE} docIntegration={DOC_INTEGRATION} /> </Storybook.Demo>
To distinguish between individuals (users) and groups (teams, organizations, etc) at glance, avatars may use different shapes. Individuals are displayed with a round avatar, but groups are displayed with a square avatar.
The <UserAvatar /> component displays an avatar for a user.
<Storybook.Demo> <UserAvatar size={PREVIEW_SIZE} user={USER} /> </Storybook.Demo>
<UserAvatar user={user} />
The <TeamAvatar /> component displays an avatar for a team.
<Storybook.Demo> <TeamAvatar size={PREVIEW_SIZE} team={TEAM} /> </Storybook.Demo>
<TeamAvatar team={team} />
The <ProjectAvatar project={project} /> component displays an avatar for a project.
<Storybook.Demo> <ProjectAvatar size={PREVIEW_SIZE} project={PROJECT} /> </Storybook.Demo>
<ProjectAvatar project={project} />
The <OrganizationAvatar /> component displays an avatar for an organization.
<Storybook.Demo> <OrganizationAvatar size={PREVIEW_SIZE} organization={ORGANIZATION} /> </Storybook.Demo>
<OrganizationAvatar organization={organization} />
The <SentryAppAvatar sentryApp={sentryApp} /> component displays an avatar for a SentryApp (integration).
<Storybook.Demo> <SentryAppAvatar size={PREVIEW_SIZE} sentryApp={SENTRY_APP} /> </Storybook.Demo>
<SentryAppAvatar sentryApp={sentryApp} />
The <DocIntegrationAvatar /> component displays an avatar for a doc integration.
<Storybook.Demo> <DocIntegrationAvatar size={PREVIEW_SIZE} docIntegration={DOC_INTEGRATION} /> </Storybook.Demo>
<DocIntegrationAvatar docIntegration={docIntegration} />
To display multiple avatars in a group, use the AvatarList component. It accepts users or teams.
export function useLoadedMembers() { const {data: members = [], isPending: fetching} = useMembers({limit: 50});
return {members, fetching}; }
export function BasicDemo() { const {teams, isLoading} = useUserTeams(); const {members, fetching} = useLoadedMembers(); if (fetching || isLoading) { return <Placeholder /> }
return <Flex direction="column" align="center" gap="md">
<AvatarList users={members} />
<AvatarList teams={teams} />
</Flex>
}
<Storybook.Demo> <BasicDemo /> </Storybook.Demo>
<AvatarList users={users} />
<AvatarList teams={teams} />
Setting both users and teams props will display both, with teams always displayed first.
export function TeamAndMembers() { const {teams, isLoading} = useUserTeams(); const {members, fetching} = useLoadedMembers();
if (isLoading || fetching) {
return <Placeholder />
}
return <AvatarList teams={teams} users={members} />
}
<Storybook.Demo> <TeamAndMembers /> </Storybook.Demo>
<AvatarList teams={teams} users={members} />
Pass the typeAvatars to customize the tooltip on the summary avatar, for example "10 other users" would become "10 other users and teams".
export function TypeAvatars() { const {teams, isLoading} = useUserTeams(); const {members, fetching} = useLoadedMembers();
if (isLoading || fetching) {
return <Placeholder />;
}
return <Fragment>
<AvatarList
teams={teams}
users={members}
maxVisibleAvatars={10}
typeAvatars="users and teams"
/>
</Fragment>
}
<Storybook.Demo> <TypeAvatars /> </Storybook.Demo>
<AvatarList teams={teams} users={users} typeAvatars="users and teams" />
The avatarSize and maxVisibleAvatars props can be used to adjust the display of an AvatarList. By default, avatarSize is 28 and maxVisibleAvatars is 5.
export function Display() { const {members, fetching} = useLoadedMembers();
if (fetching) {
return <Placeholder />
}
return <AvatarList avatarSize={48} maxVisibleAvatars={10} users={members} />
}
<Storybook.Demo> <Display /> </Storybook.Demo>
<AvatarList users={users} avatarSize={48} maxVisibleAvatars={10} />