Skip to content
Shiny.NET

Avatar & AvatarGroup

Avatar shows a person, or a thing, in a small frame. It draws their picture when there is one, their initials when there is not, and a generic silhouette when there is not even a name. An optional presence dot sits on the bottom-right corner. AvatarGroup lays avatars out as an overlapping “facepile” and collapses everyone past Max into a single +N chip.

  • NuGet downloads for Shiny.Maui.Controls
  • NuGet downloads for Shiny.Blazor.Controls
Frameworks
.NET MAUI
Blazor

MAUI (iOS)

Content, sizes, colours Presence & groups
Avatars on iOS showing a picture, initials and a silhouette, five sizes and shapes, and colour-from-name hues Presence dots on avatars and two overlapping AvatarGroups with +N overflow chips on iOS

Blazor

Content, sizes, colours Presence & groups
Picture, initials and silhouette avatars, sizes and shapes, and colour-from-name avatars in the Blazor sample Presence statuses, an overlapping AvatarGroup with a +2 chip, and a bound group with a +43 total on Blazor
  • Picture, then initials, then silhouette. The initials are drawn under the picture, so they show while it loads and stay if it fails. A broken URL never leaves a hole or a broken-image glyph.
  • Initials come from Name: the first letter of the first and last words, so Grace Brewster Hopper is GH, Jean-Luc Picard is JP and ada.lovelace@example.com is AL. Set Initials to override them.
  • ColorFromName gives each name its own stable hue. The hash is the same on both hosts, so a person gets the same colour in a MAUI app and its Blazor twin.
  • Circle, rounded-square and square shapes, at any size.
  • Presence dot: Online, Away, Busy or Offline, coloured from the theme’s success, warning, error and outline tokens.
  • AvatarGroup overlaps its avatars with a separator ring and collapses everyone past Max into a +N chip. TotalCount lets +N count everyone when only a sample is loaded.
  • Fully themed: with no colours set, both controls follow the active Shiny theme, dark mode included.
  • On MAUI, pictures load through ShinyImage, so they are cached, queued and de-duplicated like every other image in the app.
<shiny:Avatar xmlns:shiny="http://shiny.net/maui/controls"
Name="{Binding DisplayName}"
Uri="{Binding PhotoUrl}"
Size="48"
Status="Online"
Command="{Binding OpenProfileCommand}" />
<shiny:AvatarGroup Max="4" Size="32">
<shiny:Avatar Name="Grace Hopper" Uri="https://example.com/grace.jpg" />
<shiny:Avatar Name="Ada Lovelace" ColorFromName="True" />
<shiny:Avatar Name="Alan Turing" ColorFromName="True" />
<shiny:Avatar Name="Linus Torvalds" />
<shiny:Avatar Name="Margaret Hamilton" />
</shiny:AvatarGroup>

Bind a group with ItemsSource. The ItemTemplate’s root must be an Avatar. A list of strings needs no template: each string becomes an avatar with that name. An ObservableCollection is tracked.

<shiny:AvatarGroup ItemsSource="{Binding Members}"
TotalCount="{Binding MemberCount}"
Max="5"
OverflowCommand="{Binding ShowAllMembersCommand}">
<shiny:AvatarGroup.ItemTemplate>
<DataTemplate x:DataType="local:Member">
<shiny:Avatar Name="{Binding Name}" Uri="{Binding PhotoUrl}" ColorFromName="True" />
</DataTemplate>
</shiny:AvatarGroup.ItemTemplate>
</shiny:AvatarGroup>

OverflowCommand receives the hidden count (an int).

<Avatar Name="@user.DisplayName" Uri="@user.PhotoUrl" Size="48"
Status="AvatarStatus.Online" OnClick="OpenProfile" />
<AvatarGroup Max="5" TotalCount="@memberCount" Size="32" OnOverflowClick="ShowAll">
@foreach (var m in members)
{
<Avatar @key="m.Id" Name="@m.Name" Uri="@m.PhotoUrl" ColorFromName="true" />
}
</AvatarGroup>
@code {
void ShowAll(int hiddenCount) => Nav.NavigateTo("/members");
}

Handling OnClick (or the group’s OnOverflowClick) renders the avatar as a <button>. Otherwise it is a role="img" span.

Property Type (MAUI / Blazor) Default Description
Name string null Drives the initials, the accessible label and ColorFromName
Initials string null Overrides the derived initials
Uri string null Picture URL. On MAUI it can also be a resource://, file or data: URI
Source ImageSource null MAUI only. Any ImageSource, used when Uri is empty
Size double 40 / -1 (40px) Width and height
Shape AvatarShape / AvatarShape? Circle / null (circle) Circle, Rounded or Square
Status AvatarStatus None Presence dot: None, Online, Away, Busy, Offline
StatusColor Color / string theme Overrides the dot colour
FillColor Color / string theme primary container Background behind the initials or silhouette
TextColor Color / string theme on-primary-container Colour of the initials and silhouette
ColorFromName bool false A stable hue per name, with white initials, when FillColor is unset
RingColor Color / string theme surface Ring colour
RingThickness double 0 / -1 (none) Ring thickness
FontSize double -1 (auto) Size of the initials. Auto is 40% of Size, or 32% for three or more characters
Command / CommandParameter ICommand / object null MAUI. Runs on tap. Setting it makes the avatar tappable
Clicked event MAUI. Raised on tap. Subscribing makes the avatar tappable
OnClick EventCallback<MouseEventArgs> Blazor. Raised on click
DisplayInitials string (read-only) The initials actually shown
IsShowingImage bool (read-only) MAUI. True once the picture has loaded and covers the initials

An avatar with no Command and no Clicked handler takes no taps, so it never gets in the way of a list’s own row selection.

Property Type (MAUI / Blazor) Default Description
Avatars / ChildContent IList<Avatar> / RenderFragment The avatars, declared inline
ItemsSource / ItemTemplate IEnumerable / DataTemplate null MAUI only. Bind instead of declaring
Max int 0 (all) Most avatars drawn before the rest collapse into the chip. The chip itself is not counted
TotalCount int 0 The real head count when the avatars are only a sample. +N counts against this
Size double -1 When positive, the size of every avatar in the group
Shape AvatarShape? null When set, the shape of every avatar in the group
Overlap double -1 (25% of size) How far each avatar tucks under the one before it. 0 lays them side by side
RingColor Color / string theme surface Separator ring. Set it to whatever colour the group sits on
RingThickness double 2 Separator ring thickness
OverflowFormat string "+{0}" Chip text. {0} is the hidden count
OverflowCommand / OverflowClicked ICommand / event MAUI. Chip tapped. The command parameter is the hidden count
OnOverflowClick EventCallback<int> Blazor. Chip clicked, with the hidden count
OverflowCount int (read-only) How many people the chip stands for

Later avatars sit on top of earlier ones. The +N chip takes the size and shape of the first avatar, so it always matches the row.

  • MAUI: the group writes Size, Shape, RingThickness, RingColor and Margin onto the avatars it holds, so set them on the group, not on the children.
  • Blazor: size, shape, fill and ring are CSS custom properties: --shiny-avatar-size, --shiny-avatar-radius, --shiny-avatar-fill, --shiny-avatar-ink, --shiny-avatar-ring-width, --shiny-avatar-ring-color, --shiny-avatar-overlap and --shiny-avatar-font-size. The group sets them once on its root, and a parameter on a single avatar still wins.
  • Blazor: avatars must be direct children of the group. An avatar wrapped in another element, such as a tooltip or a link, is counted but can’t be hidden past Max, because hiding is done by position.
  • Blazor: the picture is a plain <img loading="lazy">, so the browser handles caching.
  • Accessibility: each avatar announces its name and status (“Grace Hopper, Online”). The group announces “4 people and 12 more”.