Avatar

macOS 13.3+

Displays a user's profile picture, with initials as a fallback.

import SwiftUIstruct AvatarUsageExample: View {    var body: some View {        HStack(spacing: FLXSpacing.md) {            FLXAvatar(size: .small) {                FLXAvatarFallback("FM")                FLXAvatarImage(url: URL(string: "https://github.com/shadcn.png"))            }            FLXAvatar(size: .medium) {                FLXAvatarFallback("FM")                FLXAvatarImage(url: URL(string: "https://github.com/shadcn.png"))            }            FLXAvatar(size: .large) {                FLXAvatarFallback("FM")                FLXAvatarImage(url: URL(string: "https://github.com/shadcn.png"))            }            FLXAvatar(size: .medium) {                FLXAvatarFallback("FM")                FLXAvatarImage(url: URL(string: "https://github.com/shadcn.png"))                FLXAvatarBadge()            }        }        .padding(FLXSpacing.xl)    }}

Installation

Requires the design system foundation (tokens and theme).

pnpm dlx shadcn@latest add https://swiftui.flexnative.com/r/mac-avatar.json

Usage

FLXAvatar(size: .medium) {    FLXAvatarFallback("FM")    FLXAvatarImage(url: URL(string: "https://github.com/shadcn.png"))}

Composition

FLXAvatar stacks its content in a ZStack. Use the following composition to build an avatar:

FLXAvatar├── FLXAvatarFallback├── FLXAvatarImage└── FLXAvatarBadge

Put FLXAvatarFallback first so it sits behind FLXAvatarImage, which stays transparent until the image finishes loading. FLXAvatarFallback uppercases its text. FLXAvatarBadge is optional and always pins itself to the bottom-trailing corner.

Sizes

Three sizes, set via size:.

FLXAvatar(size: .small) {  FLXAvatarFallback("FM")  FLXAvatarImage(url: URL(string: "https://github.com/shadcn.png"))}FLXAvatar(size: .medium) {  FLXAvatarFallback("FM")  FLXAvatarImage(url: URL(string: "https://github.com/shadcn.png"))}FLXAvatar(size: .large) {  FLXAvatarFallback("FM")  FLXAvatarImage(url: URL(string: "https://github.com/shadcn.png"))}

Badge

Overlay a status indicator by adding FLXAvatarBadge alongside the other content. The badge doesn't inherit the avatar's size, so pass a matching size: for .small and .large avatars:

FLXAvatar(size: .medium) {  FLXAvatarFallback("FM")  FLXAvatarImage(url: URL(string: "https://github.com/shadcn.png"))  FLXAvatarBadge()}

Groups

Wrap a stack of avatars in FLXAvatarGroup to overlap them, and finish the stack with FLXAvatarGroupCount for an overflow indicator:

FLXAvatarGroup {  FLXAvatar(size: .medium) {      FLXAvatarFallback("FM")      FLXAvatarImage(url: URL(string: "https://github.com/shadcn.png"))  }  FLXAvatar(size: .medium) {      FLXAvatarFallback("FM")      FLXAvatarImage(url: URL(string: "https://github.com/felipemenezes098.png"))  }  FLXAvatar(size: .medium) {      FLXAvatarFallback("PD")      FLXAvatarImage(url: URL(string: "https://github.com/peduarte.png"))  }  FLXAvatarGroupCount(count: 5, size: .medium)}

Custom styling

FLXAvatarStyle is an FLX protocol. Override it for a subtree via .flxAvatarStyle(_:):

struct FLXRingAvatarStyle: FLXAvatarStyle {  func makeBody(configuration: Configuration) -> some View {      FLXRingAvatarStyleBody(configuration: configuration)  }}struct FLXRingAvatarStyleBody: View {  @ScaledMetric(relativeTo: .body) private var scale: CGFloat = 1  let configuration: FLXAvatarStyleConfiguration  var body: some View {      ZStack {          configuration.content      }      .flxFont(configuration.size.typography)      .foregroundStyle(.orange)      .frame(width: configuration.size.diameter * scale, height: configuration.size.diameter * scale)      .padding(FLXSpacing.xs)      .overlay(          Circle().strokeBorder(              AngularGradient(colors: [.yellow, .orange, .pink, .yellow], center: .center),              lineWidth: FLXBorderWidth.thick          )      )  }}HStack(spacing: FLXSpacing.xl) {  FLXAvatar(size: .large) {      FLXAvatarFallback("FM")      FLXAvatarImage(url: URL(string: "https://github.com/shadcn.png"))  }  FLXAvatar(size: .large) {      FLXAvatarFallback("FM")      FLXAvatarImage(url: URL(string: "https://github.com/shadcn.png"))  }  .flxAvatarStyle(FLXRingAvatarStyle())}

API Reference

FLXAvatar

init(    size: FLXAvatarSize = .medium,    @ViewBuilder content: @escaping () -> Content)

FLXAvatarImage

init(url: URL?)

FLXAvatarFallback

init(_ text: String)

FLXAvatarBadge

init(size: FLXAvatarSize = .medium)

FLXAvatarGroup

init(@ViewBuilder content: @escaping () -> Content)

FLXAvatarGroupCount

init(count: Int, size: FLXAvatarSize = .medium)

Sizes

CaseDescription
smallCompact diameter, for dense lists.
mediumDefault diameter.
largeLargest diameter, for profile headers.